diff --git a/.bzrignore b/.bzrignore index a3e6f9dd2..55cbdaeeb 100644 --- a/.bzrignore +++ b/.bzrignore @@ -133,3 +133,5 @@ grub-core/gnulib/wctype.h grub-core/rs_decoder.S widthspec.bin widthspec.h +docs/stamp-1 +docs/version-dev.texi diff --git a/ChangeLog b/ChangeLog index 847d04b03..540e171cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,608 @@ +2011-05-05 Vladimir Serbinenko + + * grub-core/loader/efi/appleloader.c (MAKE_PIWG_PATH): New macro. + (devpath_1): Use MAKE_PIWG_PATH. + (devpath_2): Likewise. + (devpath_3): Likewise. + (devpath_4): Likewise. + (devpath_5): Likewise. + (devpath_6): Likewise. + + The appleldr.mod was checked that to be binary identical to previous + version. + +2011-05-05 Zach + + Support 2010 Macbooks. + + * grub-core/loader/efi/appleloader.c (devpath_6): New variable. + (devs): Add devpath_6. + +2011-05-05 Vladimir Serbinenko + + * util/grub-mkpasswd-pbkdf2.c (main): Use /dev/urandom and not + /dev/random. /dev/urandom is good enough for our purposes (salting). + +2011-05-05 Vladimir Serbinenko + + * util/grub-mkrescue.in (process_input_dir): Include efiemu??.o. + +2011-05-05 Vladimir Serbinenko + + * grub-core/lib/legacy_parse.c (grub_legacy_parse): Correctly handle + hexadecimal. + +2011-05-05 Vladimir Serbinenko + + * grub-core/efiemu/main.c (grub_efiemu_load_file): Return grub_errno + and not 0 on failure. + +2011-05-03 Colin Watson + + * grub-core/fs/i386/pc/pxe.c (grub_pxefs_dir): Return + GRUB_ERR_BAD_FS rather than GRUB_ERR_IO if the disk is not a pxe + disk; otherwise grub_fs_probe will not fall back to the next + filesystem. + (grub_pxefs_open): Likewise, for consistency. + Reported and tested by: Ezekiel Grave. + +2011-05-03 Colin Watson + + * tests/partmap_test.in: Don't hardcode path to parted. + Reported by: Peter Hjalmarsson. Fixes Savannah bug #33150. + +2011-05-01 Colin Watson + + * docs/grub.texi (GRUB only offers a rescue shell): Suggest the use + of `ls' to find out which devices are available. + +2011-04-25 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c (grub_linux_boot): Supply target rather + than source address for efi mmap buffer. + +2011-04-25 Vladimir Serbinenko + + * grub-core/partmap/amiga.c (amiga_partition_map_iterate): Fix a + wrong action on non-detecting the magic. + +2011-04-25 Vladimir Serbinenko + + * grub-core/gnulib/regex.c: Remove GRUB_MOD_LICENSE since it's + already supplied by another part of the module (fixes compilation on + FreeBSD). + +2011-04-25 Vladimir Serbinenko + + * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Make mdraid UUID + match the one used by mdadm. + +2011-04-21 Colin Watson + + * po/README: Add instructions for creating po/LINGUAS. + +2011-04-21 Colin Watson + + Add "SEE ALSO" sections to most man pages. Fixes Debian bug + #551428. + + * docs/man/grub-editenv.h2m (SEE ALSO): New section. + * docs/man/grub-emu.h2m (SEE ALSO): Likewise. + * docs/man/grub-fstest.h2m (SEE ALSO): Likewise. + * docs/man/grub-install.h2m (SEE ALSO): Likewise. + * docs/man/grub-macho2img.h2m (SEE ALSO): Likewise. + * docs/man/grub-menulst2cfg.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkconfig.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkdevicemap.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkfont.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkimage.h2m (SEE ALSO): Likewise. + * docs/man/grub-mklayout.h2m (SEE ALSO): Likewise. + * docs/man/grub-mknetdir.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkpasswd-pbkdf2.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkrelpath.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkrescue.h2m (SEE ALSO): Likewise. + * docs/man/grub-ofpathname.h2m (SEE ALSO): Likewise. + * docs/man/grub-pe2elf.h2m (SEE ALSO): Likewise. + * docs/man/grub-probe.h2m (SEE ALSO): Likewise. + * docs/man/grub-reboot.h2m (SEE ALSO): Likewise. + * docs/man/grub-script-check.h2m (SEE ALSO): Likewise. + * docs/man/grub-set-default.h2m (SEE ALSO): Likewise. + * docs/man/grub-setup.h2m (SEE ALSO): Likewise. + +2011-04-21 Colin Watson + + * grub-core/kern/emu/getroot.c + (grub_find_root_device_from_mountinfo): Remove non-virtual-device + test that was incorrectly reintroduced in r3214. + Reported by: Ian Dall. Fixes Savannah bug #33133. + +2011-04-21 Colin Watson + + Fix stack pointer handling in 16-bit relocator. + + * grub-core/lib/i386/relocator16.S (grub_relocator16_start): Move + grub_relocator16_sp to %esp rather than %ss, and zero-extend it. + Fixes Ubuntu bug #683904. + +2011-04-20 Vladimir Serbinenko + + * configure.ac: Bump version to 1.99~rc2. + +2011-04-20 Vladimir Serbinenko + + * include/grub/dl.h [ASM_FILE]: Adapt for assembly. + * grub-core/lib/i386/setjmp.S: Add missing GRUB_MOD_LICENSE. + * grub-core/lib/x86_64/setjmp.S: Likewise. + * grub-core/lib/mips/setjmp.S: Likewise. + * grub-core/lib/powerpc/setjmp.S: Likewise. + * grub-core/lib/sparc64/setjmp.S: Likewise. + +2011-04-20 Vladimir Serbinenko + + * grub-core/lib/efi/datetime.c: Add missing GRUB_MOD_LICENSE. + * grub-core/lib/efi/datetime.c: Likewise. + +2011-04-19 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_flush): + New function. + (grub_util_biosdisk_close): Use grub_util_biosdisk_flush. + * include/grub/emu/hostdisk.h (grub_util_biosdisk_flush): New proto. + * util/grub-setup.c (setup): Use grub_util_biosdisk_flush. + +2011-04-19 Vladimir Serbinenko + + * grub-core/term/gfxterm.c (grub_gfxterm_fullscreen): Preserve previous + bitmap. + (grub_gfxterm_term_init): Likewise. + +2011-04-19 Vladimir Serbinenko + + Take into account the decorations the computing menu entry width. + + * grub-core/gfxmenu/widget-box.c (get_border_width): New function. + (grub_gfxmenu_create_box): Register get_border_width. + * grub-core/gfxmenu/gui_list.c (draw_menu): Use get_border_width + if available. + * include/grub/gfxwidgets.h (grub_gfxmenu_box): New member + get_border_width. + +2011-04-18 Endres Puschner + + * grub-core/gfxmenu/icon_manager.c (grub_gfxmenu_icon_manager_get_icon): + Don't skip first class. + +2011-04-18 Vladimir Serbinenko + + * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Support huge + chunks. + * include/grub/err.h (grub_err_t): New enum value GRUB_ERR_BUG. + +2011-04-18 Vladimir Serbinenko + + Complete 64-bit division support. + + * grub-core/kern/misc.c (grub_divmod64): Rename to ... + (grub_divmod64_full): ... this. Support 64-bit divisor and reminder. + * include/grub/misc.h (grub_divmod64): Rename to ... + (grub_divmod64_full): ... this. + (grub_divmod64): New inline function. + +2011-04-18 Vladimir Serbinenko + + * util/grub-mkimage.c (generate_image): Add forgotten comma. + +2011-04-18 Vladimir Serbinenko + + * util/grub-mkimage.c (generate_image): Update fwstart.img hash after + performing the necessary test. + +2011-04-17 Vladimir Serbinenko + + * Makefile.am (multiboot.elf): Add -Wl,--build-id=none. + (kfreebsd.elf): Likewise. + (pc-chainloader.elf): Likewise. + (ntldr.elf): Likewise. + +2011-04-17 Vladimir Serbinenko + + Identify RAID by its UUID rather than (guessed) name. + + * grub-core/disk/raid.c (ascii2hex): New function. + (grub_raid_open): Accept mduuid/%s specification. + * grub-core/kern/emu/getroot.c (get_mdadm_name): Revamped into ... + (get_mdadm_uuid): ... this. + (grub_util_get_grub_dev): Use mduuid/%s if UUID is available. + +2011-04-16 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_image.c (rescale_image): Don't attempt to scale + to negative size. + +2011-04-13 Colin Watson + + * util/grub.d/10_linux.in: Add rootflags=subvol= if / is on a + btrfs subvolume. + * util/grub.d/20_linux_xen.in: Likewise. + +2011-04-13 Colin Watson + + Rewrite /proc/self/mountinfo handling to cope with bind-mounts and + move-mounts appearing out of order. Fixes Ubuntu bug #738345. + + * grub-core/kern/emu/getroot.c (find_root_device_from_mountinfo): + Build a list of relevant visible mounts using the mnt_id and + parent_mnt_id fields, and then scan that list at the end. + +2011-04-12 Colin Watson + + * docs/grub.texi (normal): New section. + (normal_exit): New section. + (Embedded configuration): Add reference to normal. + (GRUB only offers a rescue shell): Likewise. + * docs/grub-dev.texi (Error Handling): Fix typo. + +2011-04-12 Colin Watson + + * NEWS: Drop obsolete entry about probe-only btrfs support. + +2011-04-12 Colin Watson + + * util/import_gcry.py: Fix typo. + +2011-04-11 Vladimir Serbinenko + + * NEWS: Add btrfs support. + +2011-04-11 Vladimir Serbinenko +2011-04-11 Colin Watson + + BtrFS support. Written by me (Vladimir) with important bugfixes and + even more important testing by Colin. + + * Makefile.util.def (libgrubmods.a): Add crc.c and gzio.c + * grub-core/Makefile.core.def (btrfs): Add crc.c. + * grub-core/fs/btrfs.c: Stub replaced with real implementation. + * grub-core/io/gzio.c (grub_gzio): New fields mem_input_size, + mem_input_off and mem_input. All users updated to accept in-RAM input. + (gzio_seek): New function. + (test_zlib_header): Likewise. + (grub_gzio_read): Likewise. + (grub_zlib_decompress): Likewise. + * grub-core/kern/emu/getroot.c (grub_find_root_device_from_mountinfo): + Accept partial and non-virtual mounts. + (grub_guess_root_device): Do rescanning after device_from_mountinfo to + avoid receiving /dev/dm-X as device. + * grub-core/kern/emu/misc.c (grub_make_system_path_relative_to_its_root): + Handle bind and partial mounts. + * grub-core/lib/crc.c: New file. + * include/grub/deflate.h: Likewise. + * include/grub/emu/misc.h (grub_find_root_device_from_mountinfo): New + proto. + * include/grub/lib/crc.h: New file. + +2011-04-11 Vladimir Serbinenko + + Implement automatic module license checking according to new GNU + guidelines. + + * grub-core/kern/dl.c (grub_dl_check_license): New function. + (grub_dl_load_core): Use grub_dl_check_license. + * include/grub/dl.h (GRUB_MOD_SECTION): New macro. + (GRUB_MOD_LICENSE): Likewise. + (GRUB_MOD_DUAL_LICENSE): Likewise. + All modules updated. + +2011-04-11 Colin Watson + + * grub-core/fs/btrfs.c (grub_btrfs_fs) [GRUB_UTIL]: Set + reserved_first_sector to 1. btrfs reserves plenty of space for boot + loaders. + Reported by: Gene Cumm. Fixes Ubuntu bug #757446. + +2011-04-11 Vladimir Serbinenko + + * util/grub-fstest.c (cmd_cmp): Check that sizes match. + +2011-04-11 Vladimir Serbinenko + + * util/grub-fstest.c (read_file): Report GRUB error if file opening + failed. + +2011-04-11 Vladimir Serbinenko + + * grub-core/kern/file.c (grub_file_open): Don't take into account the + parenthesis in the middle of the filename. + +2011-04-10 Vladimir Serbinenko + + * grub-core/loader/mips/linux.c (grub_cmd_initrd): Use correct limits + rather than trying to put initrd way too high. + Reported by: Ryan Lortie + +2011-04-10 Vladimir Serbinenko + + * grub-core/boot/mips/yeeloong/fwstart.S (no_cs5536): Put back + improperly removed string. + +2011-04-10 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_data): New member + is_disk. + (grub_util_biosdisk_open): Don't apply ioctl on non-disk devices. + (open_device) Likewise. + (grub_util_biosdisk_close): Likewise. + Reported by: Mark Korenberger. + +2011-04-10 Alexander Kurtz + + * util/grub-mkconfig_lib.in: Add missing quotes. + +2011-04-10 Colin Watson + + * grub-core/gnulib/argp-parse.c (__argp_input): Don't crash if pstate + is NULL. + +2011-04-10 Vladimir Serbinenko + + Dynamically count the number of lines for the lower banner. + + * grub-core/normal/menu_entry.c (per_term_screen): New member + num_entries. + (print_down): Use num_entries. + (update_screen): Likewise. + (grub_menu_entry_run): Set num_entries. + * grub-core/normal/menu_text.c (menu_viewer_data): New member + num_entries. + (grub_print_message_indented): Move real part to ... + (grub_print_message_indented_real): ... here. Additional argument + dry_run. + (draw_border): Additional argument num_entries. + (print_message): Additional argument dry_run. + (print_entries): Receive menu viewer data. + (grub_menu_init_page): New argment num_entries. + (menu_text_set_chosen_entry): Use num_entries. + (grub_menu_try_text): Likewise. + * grub-core/normal/term.c (print_ucs4_terminal): New argument dry_run. + All users updated. + (grub_ucs4_count_lines): New function. + * include/grub/term.h (grub_term_cursor_x): Moved from here .. + * grub-core/normal/menu_text.c (grub_term_cursor_x): ... to here. + * include/grub/term.h (GRUB_TERM_MESSAGE_HEIGHT): Removed. + (grub_term_border_height): Likewise. + (grub_term_num_entries): Likewise. + +2011-04-10 Vladimir Serbinenko + + * grub-core/boot/mips/yeeloong/fwstart.S: Fix address to error message. + Remove now unused string. + +2011-04-09 Colin Watson + + * docs/grub-dev.texi (Finding your way around): Update for 1.99 + build system. + (Getting started): GRUB is developed in Bazaar now, not Subversion. + + (Comment): Fix typo. + (Getting started): General copy-editing. + (Typical Development Experience): Likewise. + (Error Handling): Likewise. + (Video API): Likewise. + +2011-04-09 Colin Watson + + * docs/grub-dev.texi: Replace MoinMoin syntax with Texinfo syntax + throughout. + +2011-04-08 Vladimir Serbinenko + + * util/grub-mkimage.c (main): Handle special naming of yeeloong + directory. + +2011-04-08 Colin Watson + + * docs/grub-dev.texi: Fix spelling of "developer" throughout. + * grub-core/fs/i386/pc/pxe.c (parse_dhcp_vendor): Fix spelling of + "development". + +2011-04-08 Vladimir Serbinenko + + * grub-core/normal/menu_entry.c (run): Use grub_memcpy rather than + grub_strcpy since the lines aren't necessarily 0-terminated. + +2011-04-08 Vladimir Serbinenko + + * grub-core/lib/legacy_parse.c (legacy_commands): Find doesn't set + root on legacy. + +2011-04-08 Vladimir Serbinenko + + * grub-core/commands/probe.c (options): Argument to set isn't optional. + (GRUB_MOD_INIT): DEVICE isn't optional. + +2011-04-08 Vladimir Serbinenko + + * grub-core/normal/term.c (print_ucs4_terminal): Don't try to put the + word on new line if it's too long anyway. Fixes a hang. + +2011-04-08 Vladimir Serbinenko + + * include/grub/util/raid.h (grub_util_raid_getmembers): Make argument + const. + * util/grub-setup.c (main): Reuse md device name if available. + * util/raid.c (grub_util_raid_getmembers): Receive device name and + not GRUB name as argument. + Based on patch by: Florian Wagner . + +2011-04-08 Vladimir Serbinenko + + * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_make_mbi): + Place mbi on low memory for better compatibility. + +2011-04-08 Vladimir Serbinenko + + * include/grub/efiemu/efiemu.h: Use grub_memory_hook_t type. + +2011-04-08 Vladimir Serbinenko +2011-04-08 Colin Watson + + * autogen.sh: Ensure that collate and ctype locale is C. + * conf/Makefile.common: Likewise. + +2011-04-08 Vladimir Serbinenko + + * grub-core/normal/menu.c: Add missing include. + +2011-04-08 Vladimir Serbinenko + + * grub-core/disk/raid.c [GRUB_UTIL]: Add missing include. + +2011-04-08 Martin Zuther + + * util/grub-mkconfig.in: Ignore emacsen backup. + +2011-04-08 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (open_device): Sync on close and not + on open. + (grub_util_biosdisk_close): Likewise. + +2011-04-08 Vladimir Serbinenko + + * grub-core/kern/emu/getroot.c (grub_util_get_grub_dev): Add missing + const attribute and use grub_isdigit. + +2011-04-06 Andrey + + * grub-core/video/fb/video_fb.c (grub_video_fb_setup): Silence older + gcc warning. + +2011-04-06 Vladimir Serbinenko + + * grub-core/lib/relocator.c (grub_relocator_alloc_chunk_align): Add few + useful grub_dprintf's. + +2011-04-06 Vladimir Serbinenko + + * include/grub/fs.h (grub_dirhook_info): Use unsigned for 1-bit fields. + +2011-04-06 Vladimir Serbinenko + + * util/grub.d/00_header.in: Don't use LANG unless unifont is available. + +2011-04-06 Vladimir Serbinenko + + Output errors if theme loading failed. + + * grub-core/gfxmenu/gfxmenu.c (grub_gfxmenu_try): Move the call to + grub_gfxterm_fullscreen on error paths to ... + * grub-core/normal/menu.c (menu_init): ...here. Wait after showing + theme loading error. + +2011-04-06 Vladimir Serbinenko + + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_RAW_SIZE): Let a bit more + space for older compilers. + (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): Likewise. + +2011-04-06 Vladimir Serbinenko + + * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Detect spares + and report them as not RAID members since they are useless for GRUB. + * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise. + +2011-04-02 Vladimir Serbinenko + + Increase LVM implementation robustness in order not to crash on + configurations like pvmove. Previously code assumed that in some places + only lvs or only pvs are used whereas it seems that they are used + interchangeably. + + * grub-core/disk/lvm.c (read_node): New function. + (read_lv): Use read_node. + (grub_lvm_scan_device): Use only first mirror on pvmove'd lvs. + Match volumes only at the end when all lvs are found. Take both + pvs (first) and lvs (second) into account. + * include/grub/lvm.h (grub_lvm_segment): Merge fields stripe_* and + mirror_* into node_*. All users updated. + (grub_lvm_stripe): Merge this ... + (grub_lvm_mirror): ... and this ... + (grub_lvm_node): ... into this. All users updated. + +2011-04-02 Vladimir Serbinenko + + * grub-core/disk/lvm.c (grub_lvm_scan_device): Print errors on the end + of function to allow further scanning for LVMs. + +2011-04-02 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_read): Don't close + on failed seek as it breaks open fd reusage. + +2011-04-02 Vladimir Serbinenko + + * util/grub-install.in: Add a recommendation to use --recheck before + reporting bugs. + +2011-04-02 Vladimir Serbinenko + + * docs/grub.texi (Vendor power-on buttons): Explain how the numbers + are obtained. + +2011-04-02 Vladimir Serbinenko + + GRUB developper manual based on existing Internals section and + contributions by the various authors with active copyright assignment. + + * docs/Makefile.am (info_TEXINFOS): Add grub-dev.texi. + * docs/font_char_metrics.png: New file. + * docs/font_char_metrics.txt: Likewise. + * docs/grub-dev.texi: Likewise. + * docs/grub.texi (Internals): Move from here ... + * docs/grub-dev.texi: ... here. + +2011-04-01 Colin Watson + + Store the loopback device as data on loopback grub_disk structures, + rather than the file it points to. This fixes use of freed memory + if an existing loopback device is replaced. + + * grub-core/disk/loopback.c (grub_loopback_open): Store dev in + disk->data, not dev->file. + (grub_loopback_read): Adjust file assignment to match. + Fixes Ubuntu bug #742967. + +2011-04-01 Colin Watson + + * grub-core/disk/loopback.c (grub_cmd_loopback): Fix a memory leak + when replacing an existing device. + +2011-04-01 Vladimir Serbinenko + + Fix incorrect types in jfs.c. This enables >2TiB disks and fixes some + memory corruptions. + + * grub-core/fs/jfs.c (struct grub_jfs_diropen): Interpret bytes as + unsigned. + (grub_jfs_lookup_symlink): Make ino a grub_uint32_t rather than int. + (grub_jfs_blkno): Use 64-bit quantities for block sectors. + (grub_jfs_read_inode): Likewise. + (grub_jfs_opendir): Likewise. Remove now useless casts. + (grub_jfs_getent): Likewise. + Make ino a grub_uint32_t rather than int. + (grub_jfs_mount): Ensure that blksize and log2_blksize are consistent. + (grub_jfs_read_file): Use 64-bit quantities when necessary. Replace + division and module with bit operations. + (grub_jfs_find_file): Make ino a grub_uint32_t. + (grub_jfs_lookup_symlink): Likewise. Use 64-bit quantities + +2011-04-01 Colin Watson + + * grub-core/normal/menu_entry.c (run): Quieten uninitialised + warning. (This was in fact always initialised before use, but GCC + wasn't smart enough to prove that.) + * grub-core/script/lexer.c (grub_script_lexer_yywrap): Likewise. + 2011-03-31 Vladimir Serbinenko * grub-core/kern/x86_64/efi/callwrap.S (efi_wrap_0): Preserve 16-byte diff --git a/Makefile.am b/Makefile.am index 60e041a8d..9301c91a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -147,28 +147,28 @@ linux.init.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" multiboot.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S - $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include + $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include kfreebsd.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S - $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include + $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include kfreebsd.aout: kfreebsd.elf $(OBJCOPY) -O a.out-i386-linux $< $@ -R .note.gnu.build-id pc-chainloader.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S - $(TARGET_CC) -o $@ $< -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x7c00 -m32 + $(TARGET_CC) -o $@ $< -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x7c00 -m32 pc-chainloader.bin: pc-chainloader.elf $(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@; ntldr.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S - $(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0 -m32 + $(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0 -m32 ntldr.bin: ntldr.elf $(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@; multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S - $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1 + $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1 kfreebsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kfreebsd.init-x86_64.S $(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@ diff --git a/Makefile.util.def b/Makefile.util.def index 0f7643b58..79ab040dd 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -85,6 +85,7 @@ library = { common = grub-core/lib/LzFind.c; common = grub-core/lib/LzmaEnc.c; common = grub-core/lib/pbkdf2.c; + common = grub-core/lib/crc.c; common = grub-core/normal/datetime.c; common = grub-core/normal/misc.c; common = grub-core/partmap/acorn.c; @@ -100,6 +101,7 @@ library = { common = grub-core/script/main.c; common = grub-core/script/script.c; common = grub-core/script/argv.c; + common = grub-core/io/gzio.c; }; program = { diff --git a/NEWS b/NEWS index 36e3f25bf..2a93c2526 100644 --- a/NEWS +++ b/NEWS @@ -29,7 +29,7 @@ New in 1.99: * New `lsacpi' command. -* Basic btrfs support (detection and UUID). +* Btrfs support. * New `--boot-directory' option to `grub-install', `grub-reboot', and `grub-set-default', with clearer semantics than the previous @@ -83,10 +83,6 @@ New in 1.99: * Extensive updates to the Texinfo documentation. -* Add `grub-probe' support for the btrfs filesystem, permitting / to - reside on btrfs as long as /boot is on a filesystem natively supported - by GRUB. - * Handle symbolic links under /dev/mapper on GNU/Linux. * Handle installation across multiple partition table types. diff --git a/autogen.sh b/autogen.sh index 96b1e33e2..d14707aad 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,6 +2,10 @@ set -e +export LC_CTYPE=C +export LC_COLLATE=C +unset LC_ALL + autogen --version >/dev/null || exit 1 echo "Importing unicode..." diff --git a/conf/Makefile.common b/conf/Makefile.common index 32ca76d08..5aa13cdd6 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -2,6 +2,10 @@ CFLAGS_PLATFORM= +export LC_COLLATE := C +export LC_CTYPE := C +unexport LC_ALL + # Platform specific options if COND_i386_pc CFLAGS_PLATFORM += -mrtd -mregparm=3 diff --git a/configure.ac b/configure.ac index f9e974bca..811bd992d 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ dnl type, so there is no conflict. Variables with the prefix "TARGET_" dnl (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for the target dnl type. -AC_INIT([GRUB],[1.99~rc1],[bug-grub@gnu.org]) +AC_INIT([GRUB],[1.99~rc2],[bug-grub@gnu.org]) AC_CONFIG_AUX_DIR([build-aux]) diff --git a/docs/Makefile.am b/docs/Makefile.am index 8d9fb8445..6e1500601 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS = subdir-objects # AM_MAKEINFOFLAGS = --no-split --no-validate -info_TEXINFOS = grub.texi +info_TEXINFOS = grub.texi grub-dev.texi grub_TEXINFOS = fdl.texi diff --git a/docs/font_char_metrics.png b/docs/font_char_metrics.png new file mode 100644 index 000000000..8d10d1f64 Binary files /dev/null and b/docs/font_char_metrics.png differ diff --git a/docs/font_char_metrics.txt b/docs/font_char_metrics.txt new file mode 100644 index 000000000..92f1371fd --- /dev/null +++ b/docs/font_char_metrics.txt @@ -0,0 +1 @@ +Please fill this in. diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi new file mode 100644 index 000000000..93d2bdb4d --- /dev/null +++ b/docs/grub-dev.texi @@ -0,0 +1,1533 @@ +\input texinfo +@c -*-texinfo-*- +@c %**start of header +@setfilename grub-dev.info +@include version-dev.texi +@settitle GNU GRUB Developers Manual @value{VERSION} +@c Unify all our little indices for now. +@syncodeindex fn cp +@syncodeindex vr cp +@syncodeindex ky cp +@syncodeindex pg cp +@syncodeindex tp cp +@c %**end of header + +@footnotestyle separate +@paragraphindent 3 +@finalout + +@copying +This developer manual is for GNU GRUB (version @value{VERSION}, +@value{UPDATED}). + +Copyright @copyright{} 1999,2000,2001,2002,2004,2005,2006,2008,2009,2010,2011 Free Software Foundation, Inc. + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.2 or +any later version published by the Free Software Foundation; with no +Invariant Sections. +@end quotation +@end copying + +@dircategory Kernel +@direntry +* grub-dev: (grub-dev). The GRand Unified Bootloader Dev +@end direntry + +@setchapternewpage odd + +@titlepage +@sp 10 +@title the GNU GRUB developer manual +@subtitle The GRand Unified Bootloader, version @value{VERSION}, @value{UPDATED}. +@author Yoshinori K. Okuji +@author Colin D Bennett +@author Vesa Jääskeläinen +@author Colin Watson +@author Robert Millan +@author Carles Pina +@c The following two commands start the copyright page. +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@c Output the table of contents at the beginning. +@contents + +@finalout +@headings double + +@ifnottex +@node Top +@top GNU GRUB developer manual + +This is the developer documentation of GNU GRUB, the GRand Unified Bootloader, +a flexible and powerful boot loader program for a wide range of +architectures. + +This edition documents version @value{VERSION}. + +@insertcopying +@end ifnottex + +@menu +* Getting the source code:: +* Finding your way around:: +* Coding style:: +* Contributing Changes:: +* Error Handling:: +* CIA:: +* BIOS port memory map:: +* Video Subsystem:: +* PFF2 Font File Format:: +* Graphical Menu Software Design:: +* Copying This Manual:: Copying This Manual +* Index:: +@end menu + + +@node Getting the source code +@chapter Getting the source code + +GRUB is maintained using the @uref{http://bazaar-vcs.org/, Bazaar revision +control system}. To fetch the primary development branch: + +@example +bzr get http://bzr.savannah.gnu.org/r/grub/trunk/grub +@end example + +The GRUB developers maintain several other branches with work in progress. +Of these, the most interesting is the experimental branch, which is a +staging area for new code which we expect to eventually merge into trunk but +which is not yet ready: + +@example +bzr get http://bzr.savannah.gnu.org/r/grub/branches/experimental +@end example + +Once you have used @kbd{bzr get} to fetch an initial copy of a branch, you +can use @kbd{bzr pull} to keep it up to date. If you have modified your +local version, you may need to resolve conflicts when pulling. + +@node Coding style +@chapter Coding style +@c By YoshinoriOkuji, VesaJääskeläinen and ColinBennett + +Basically we follow the @uref{http://www.gnu.org/prep/standards_toc.html, GNU Coding Standards}. We define additional conventions for GRUB here. + +@menu +* Naming Conventions:: +* Functions:: +* Variables:: +* Types:: +* Macros:: +* Comments:: +* Multi-Line Comments:: +@end menu + +@node Naming Conventions +@section Naming Conventions + +All global symbols (i.e. functions, variables, types, and macros) must have the prefix grub_ or GRUB_. The all capital form is used only by macros. + +@node Functions +@section Functions + +If a function is global, its name must be prefixed with grub_ and must consist of only small letters. If the function belongs to a specific function module, the name must also be prefixed with the module name. For example, if a function is for file systems, its name is prefixed with grub_fs_. If a function is for FAT file system but not for all file systems, its name is prefixed with grub_fs_fat_. The hierarchy is noted this way. + +After a prefix, a function name must start with a verb (such as get or is). It must not be a noun. Some kind of abbreviation is permitted, as long as it wouldn't make code less readable (e.g. init). + +If a function is local, its name may not start with any prefix. It must start with a verb. + +@node Variables +@section Variables + +The rule is mostly the same as functions, as noted above. If a variable is global, its name must be prefixed with grub_ and must consist of only small letters. If the variable belongs to a specific function module, the name must also be prefixed with the module name. For example, if a function is for dynamic loading, its name is prefixed with grub_dl_. If a variable is for ELF but not for all dynamic loading systems, its name is prefixed with grub_dl_elf_. + +After a prefix, a variable name must start with a noun or an adjective (such as name or long) and it should end with a noun. Some kind of abbreviation is permitted, as long as it wouldn't make code less readable (e.g. i18n). + +If a variable is global in the scope of a single file (i.e. it is declared with static), its name may not start with any prefix. It must start with a noun or an adjective. + +If a variable is local, you may choose any shorter name, as long as it wouldn't make code less readable (e.g. i). + +@node Types +@section Types + +The name of a type must be prefixed with grub_ and must consist of only small letters. If the type belongs to a specific function module, the name must also be prefixed with the module name. For example, if a type is for OS loaders, its name is prefixed with grub_loader_. If a type is for Multiboot but not for all OS loaders, its name is prefixed with grub_loader_linux_. + +The name must be suffixed with _t, to emphasize the fact that it is a type but not a variable or a function. + +@node Macros +@section Macros + +If a macro is global, its name must be prefixed with GRUB_ and must consist of only large letters. Other rules are the same as functions or variables, depending on whether a macro is used like a function or a variable. + +@node Comments +@section Comments + +All comments shall be C-style comments, of the form @samp{/* @dots{} */}. + +Comments shall be placed only on a line by themselves. They shall not be placed together with code, variable declarations, or other non-comment entities. A comment should be placed immediately preceding the entity it describes. + +Acceptable: +@example +/* The page # that is the front buffer. */ +int displayed_page; +/* The page # that is the back buffer. */ +int render_page; +@end example + +Unacceptable: +@example +int displayed_page; /* The page # that is the front buffer. */ +int render_page; /* The page # that is the back buffer. */ +@end example + +@node Multi-Line Comments +@section Multi-Line Comments + +Comments spanning multiple lines shall be formatted with all lines after the first aligned with the first line. + +Asterisk characters should not be repeated a the start of each subsequent line. + +Acceptable: +@example +/* This is a comment + which spans multiple lines. + It is long. */ +@end example + +Unacceptable: +@example +/* + * This is a comment + * which spans multiple lines. + * It is long. */ +@end example + +The opening @samp{/*} and closing @samp{*/} should be placed together on a line with text. + +@node Finding your way around +@chapter Finding your way around + +Here is a brief map of the GRUB code base. + +GRUB uses Autoconf and Automake, with most of the Automake input generated +by AutoGen. The top-level build rules are in @file{configure.ac}, +@file{grub-core/Makefile.core.def}, and @file{Makefile.util.def}. Each +block in a @file{*.def} file represents a build target, and specifies the +source files used to build it on various platforms. The @file{*.def} files +are processed into AutoGen input by @file{gentpl.py} (which you only need to +look at if you are extending the build system). If you are adding a new +module which follows an existing pattern, such as a new command or a new +filesystem implementation, it is usually easiest to grep +@file{grub-core/Makefile.core.def} and @file{Makefile.util.def} for an +existing example of that pattern to find out where it should be added. + +In general, code that may be run at boot time is in a subdirectory of +@file{grub-core}, while code that is only run from within a full operating +system is in a subdirectory of the top level. + +Low-level boot code, such as the MBR implementation on PC BIOS systems, is +in the @file{grub-core/boot/} directory. + +The GRUB kernel is in @file{grub-core/kern/}. This contains core facilities +such as the device, disk, and file frameworks, environment variable +handling, list processing, and so on. The kernel should contain enough to +get up to a rescue prompt. Header files for kernel facilities, among +others, are in @file{include/}. + +Terminal implementations are in @file{grub-core/term/}. + +Disk access code is spread across @file{grub-core/disk/} (for accessing the +disk devices themselves), @file{grub-core/partmap/} (for interpreting +partition table data), and @file{grub-core/fs/} (for accessing filesystems). +Note that, with the odd specialised exception, GRUB only contains code to +@emph{read} from filesystems and tries to avoid containing any code to +@emph{write} to filesystems; this lets us confidently assure users that GRUB +cannot be responsible for filesystem corruption. + +PCI and USB bus handling is in @file{grub-core/bus/}. + +Video handling code is in @file{grub-core/video/}. The graphical menu +system uses this heavily, but is in a separate directory, +@file{grub-core/gfxmenu/}. + +Most commands are implemented by files in @file{grub-core/commands/}, with +the following exceptions: + +@itemize +@item +A few core commands live in @file{grub-core/kern/corecmd.c}. + +@item +Commands related to normal mode live under @file{grub-core/normal/}. + +@item +Commands that load and boot kernels live under @file{grub-core/loader/}. + +@item +The @samp{loopback} command is really a disk device, and so lives in +@file{grub-core/disk/loopback.c}. + +@item +The @samp{gettext} command lives under @file{grub-core/gettext/}. + +@item +The @samp{loadfont} and @samp{lsfonts} commands live under +@file{grub-core/font/}. + +@item +The @samp{serial}, @samp{terminfo}, and @samp{background_image} commands +live under @file{grub-core/term/}. + +@item +The @samp{efiemu_*} commands live under @file{grub-core/efiemu/}. +@end itemize + +There are a few other special-purpose exceptions; grep for them if they +matter to you. + +Utility programs meant to be run from a full operating system are in +@file{util/}. + +@node Contributing Changes +@chapter Contributing changes +@c By YoshinoriOkuji, VesaJääskeläinen, ColinWatson + +Contributing changes to GRUB 2 is welcomed activity. However we have a +bit of control what kind of changes will be accepted to GRUB 2. +Therefore it is important to discuss your changes on grub-devel mailing list +(see MailingLists). On this page there are some basic details on the +development process and activities. + +First of all you should come up with the idea yourself what you want to +contribute. If you do not have that beforehand you are advised to study this +manual and try GRUB 2 out to see what you think is missing from there. + +Here are additional pointers: +@itemize +@item @url{https://savannah.gnu.org/task/?group=grub GRUB's Task Tracker} +@item @url{https://savannah.gnu.org/bugs/?group=grub GRUB's Bug Tracker} +@end itemize + +If you intended to make changes to GRUB Legacy (<=0.97) those are not accepted +anymore. + +@menu +* Getting started:: +* Typical Developer Experience:: +* When you are approved for write access to project's files:: +@end menu + +@node Getting started +@section Getting started + +@itemize +@item Always use latest GRUB 2 source code. So get that first. + +For developers it is recommended always to use the newest development version of GRUB 2. If development takes a long period of time, please remember to keep in sync with newest developments regularly so it is much easier to integrate your change in the future. GRUB 2 is being developed in a Bazaar (bzr) repository. + +Please check Savannah's GRUB project page for details how to get newest bzr: +@uref{http://savannah.gnu.org/bzr/?group=grub, GRUB 2 bzr Repository} + +@item Compile it and try it out. + +It is always good idea to first see that things work somehow and after that +to start to implement new features or develop fixes to bugs. + +@item Study the code. + +There are sometimes odd ways to do things in GRUB 2 code base. +This is mainly related to limited environment where GRUB 2 is being executed. +You usually do not need to understand it all so it is better to only try to +look at places that relates to your work. Please do not hesitate to ask for +help if there is something that you do not understand. + +@item Develop a new feature. + +Now that you know what to do and how it should work in GRUB 2 code base, please +be free to develop it. If you have not so far announced your idea on grub-devel +mailing list, please do it now. This is to make sure you are not wasting your +time working on the solution that will not be integrated to GRUB 2 code base. + +You might want to study our coding style before starting development so you +do not need to change much of the code when your patch is being reviewed. +(see @ref{Coding style}) + +For every accepted patch there has to exist a ChangeLog entry. Our ChangeLog +consist of changes within source code and are not describing about what the +change logically does. Please see examples from previous entries. + +Also remember that GRUB 2 is licensed under GPLv3 license and that usually +means that you are not allowed to copy pieces of code from other projects. +Even if the source project's license would be compatible with GPLv3, please +discuss it beforehand on grub-devel mailing list. + +@item Test your change. + +Test that your change works properly. Try it out a couple of times, preferably on different systems, and try to find problems with it. + +@item Publish your change. + +When you are happy with your change, first make sure it is compilable with +latest development version of GRUB 2. After that please send a patch to +grub-devel for review. Please describe in your email why you made the change, +what it changes and so on. Please be prepared to receive even discouraging +comments about your patch. There is usually at least something that needs +to be improved in every patch. + +Please use unified diff to make your patch (good match of arguments for diff is @samp{-pruN}). + +@item Respond to received feedback. + +If you are asked to modify your patch, please do that and resubmit it for +review. If your change is large you are required to submit a copyright +agreement to FSF. Please keep in mind that if you are asked to submit +for copyright agreement, process can take some time and is mandatory +in order to get your changes integrated. + +If you are not on grub-devel to respond to questions, most likely your patch +will not be accepted. Also if problems arise from your changes later on, +it would be preferable that you also fix the problem. So stay around +for a while. + +@item Your patch is accepted. + +Good job! Your patch will now be integrated into GRUB 2 mainline, and if it didn't break anything it will be publicly available in the next release. + +Now you are welcome to do further improvements :) +@end itemize + +@node Typical Developer Experience +@section Typical Developer Experience + +The typical experience for a developer in this project is the following: + +@enumerate +@item You find yourself wanting to do something (e.g. fixing a bug). +@item You show some result in the mailing list or the IRC. +@item You are getting to be known to other developers. +@item You accumulate significant amount of contribution, so copyright assignment is processed. +@item You are free to check in your changes on your own, legally speaking. +@end enumerate + +At this point, it is rather annoying that you ought to ask somebody else every +change to be checked in. For efficiency, it is far better, if you can commit +it yourself. Therefore, our policy is to give you the write permission to our +official repository, once you have shown your skill and will, +and the FSF clerks have dealt with your copyright assignment. + +@node When you are approved for write access to project's files +@section When you are approved for write access to project's files + +As you might know, GRUB is hosted on +@url{https://savannah.gnu.org/projects/grub Savannah}, thus the membership +is managed by Savannah. This means that, if you want to be a member of this +project: + +@enumerate +@item You need to create your own account on Savannah. +@item You can submit ``Request for Inclusion'' from ``My Groups'' on Savannah. +@end enumerate + +Then, one of the admins can approve your request, and you will be a member. +If you don't want to use the Savannah interface to submit a request, you can +simply notify the admins by email or something else, alternatively. But you +still need to create an account beforehand. + +NOTE: we sometimes receive a ``Request for Inclusion'' from an unknown person. +In this case, the request would be just discarded, since it is too dangerous +to allow a stranger to be a member, which automatically gives him a commit +right to the repository, both for a legal reason and for a technical reason. + +If your intention is to just get started, please do not submit a inclusion +request. Instead, please subscribe to the mailing list, and communicate first +(e.g. sending a patch, asking a question, commenting on another message...). + +@node Error Handling +@chapter Error Handling + +Error handling in GRUB 2 is based on exception handling model. As C language +doesn't directly support exceptions, exception handling behavior is emulated +in software. + +When exception is raised, function must return to calling function. If calling +function does not provide handling of the exception it must return back to its +calling function and so on, until exception is handled. If exception is not +handled before prompt is displayed, error message will be shown to user. + +Exception information is stored on @code{grub_errno} global variable. If +@code{grub_errno} variable contains value @code{GRUB_ERR_NONE}, there is no active +exception and application can continue normal processing. When @code{grub_errno} has +other value, it is required that application code either handles this error or +returns instantly to caller. If function is with return type @code{grub_err_t} is +about to return @code{GRUB_ERR_NONE}, it should not set @code{grub_errno} to that +value. Only set @code{grub_errno} in cases where there is error situation. + +Simple exception forwarder. +@example +grub_err_t +forwarding_example (void) +@{ + /* Call function that might cause exception. */ + foobar (); + + /* No special exception handler, just forward possible exceptions. */ + if (grub_errno != GRUB_ERR_NONE) + @{ + return grub_errno; + @} + + /* All is OK, do more processing. */ + + /* Return OK signal, to caller. */ + return GRUB_ERR_NONE; +@} +@end example + +Error reporting has two components, the actual error code (of type +@code{grub_err_t}) and textual message that will be displayed to user. List of +valid error codes is listed in header file @file{include/grub/err.h}. Textual +error message can contain any textual data. At time of writing, error message +can contain up to 256 characters (including terminating NUL). To ease error +reporting there is a helper function @code{grub_error} that allows easier +formatting of error messages and should be used instead of writing directly to +global variables. + +Example of error reporting. +@example +grub_err_t +failing_example () +@{ + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "Failed to read %s, tried %d times.", + "test.txt", + 10); +@} +@end example + +If there is a special reason that error code does not need to be taken account, +@code{grub_errno} can be zeroed back to @code{GRUB_ERR_NONE}. In cases like this all +previous error codes should have been handled correctly. This makes sure that +there are no unhandled exceptions. + +Example of zeroing @code{grub_errno}. +@example +grub_err_t +probe_example () +@{ + /* Try to probe device type 1. */ + probe_for_device (); + if (grub_errno == GRUB_ERR_NONE) + @{ + /* Device type 1 was found on system. */ + register_device (); + return GRUB_ERR_NONE; + @} + /* Zero out error code. */ + grub_errno = GRUB_ERR_NONE; + + /* No device type 1 found, try to probe device type 2. */ + probe_for_device2 (); + if (grub_errno == GRUB_ERR_NONE) + @{ + /* Device type 2 was found on system. */ + register_device2 (); + return GRUB_ERR_NONE; + @} + /* Zero out error code. */ + grub_errno = GRUB_ERR_NONE; + + /* Return custom error message. */ + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No device type 1 or 2 found."); +@} +@end example + +Some times there is a need to continue processing even if there is a error +state in application. In situations like this, there is a needed to save old +error state and then call other functions that might fail. To aid in this, +there is a error stack implemented. Error state can be pushed to error stack +by calling function @code{grub_error_push ()}. When processing has been completed, +@code{grub_error_pop ()} can be used to pop error state from stack. Error stack +contains predefined amount of error stack items. Error stack is protected for +overflow and marks these situations so overflow error does not get unseen. +If there is no space available to store error message, it is simply discarded +and overflow will be marked as happened. When overflow happens, it most likely +will corrupt error stack consistency as for pushed error there is no matching +pop, but overflow message will be shown to inform user about the situation. +Overflow message will be shown at time when prompt is about to be drawn. + +Example usage of error stack. +@example +/* Save possible old error message. */ +grub_error_push (); + +/* Do your stuff here. */ +call_possibly_failing_function (); + +if (grub_errno != GRUB_ERR_NONE) + @{ + /* Inform rest of the code that there is error (grub_errno + is set). There is no pop here as we want both error states + to be displayed. */ + return; + @} + +/* Restore old error state by popping previous item from stack. */ +grub_error_pop (); +@end example + +@node CIA +@chapter CIA +@c By Robert Millan and Carles Pina +If you have commit access, please setup CIA in your Bazaar +config so those in IRC receive notification of your commits. + +In @file{~/.bazaar/bazaar.conf}, add "cia_send_revno = true". +Optionally, you can also add "cia_user = myusername" if you'd +like CIA service to use a specific account (for statistical purpose). + +In the @file{.bzr/branch/branch.conf} of your checkout branch, +"set nickname = /path_to_this_branch" and "cia_project = GNU GRUB". + +Additionally, please set cia_send_revno in the [DEFAULT] section +of your @file{~/.bazaar/bazaar.conf}. E.g.: + +@example +[DEFAULT] +cia_send_revno = true +@end example + +Remember to install cia-clients (Debian/Ubuntu package) to be able to use CIA. + +Keep in mind Bazaar sends notifications for all commits to branches that have +this setting, regardless of whether they're bound branches (checkouts) or not. +So if you make local commits in a non-bound branch and it bothers you that +others can read them, do not use this setting. + +@node BIOS port memory map +@chapter BIOS port memory map +@c By Yoshinori K Okuji + +@multitable @columnfractions .15 .25 .5 +@headitem Start @tab End @tab Usage +@item 0 @tab 0x1000 - 1 @tab BIOS and real mode interrupts +@item 0x07BE @tab 0x07FF @tab Partition table passed to another boot loader +@item ? @tab 0x2000 - 1 @tab Real mode stack +@item 0x7C00 @tab 0x7D00 - 1 @tab Boot sector +@item 0x8000 @tab ? @tab GRUB kernel +@item 0x68000 @tab 0x78000 - 1 @tab Disk buffer +@item ? @tab 0x80000 - 1 @tab Protected mode stack +@item 0x80000 @tab ? @tab Heap +@item ? @tab 0xA0000 - 1 @tab Extended BIOS Data Area +@item 0xA0000 @tab 0xC0000 - 1 @tab Video RAM +@item 0xC0000 @tab 0x100000 - 1 @tab BIOS +@item 0x100000 @tab ? @tab Heap and module code +@end multitable + +@node Video Subsystem +@chapter Video Subsystem +@c By VesaJääskeläinen +This document contains specification for Video Subsystem for GRUB2. +Currently only the usage interface is described in this document. +Internal structure of how video drivers are registering and how video +driver manager works are not included here. + +@menu +* Video API:: +* Bitmap API:: +* Example usage of Video API:: +@end menu + +@node Video API +@section Video API + +@subsection grub_video_setup + +@itemize +@item Prototype: +@example +grub_err_t +grub_video_setup (unsigned int width, unsigned int height, unsigned int mode_type); +@end example +@item Description: + +Driver will use information provided to it to select best possible video mode and switch to it. Supported values for @code{mode_type} are @code{GRUB_VIDEO_MODE_TYPE_INDEX_COLOR} for index color modes, @code{GRUB_VIDEO_MODE_TYPE_RGB} for direct RGB color modes and @code{GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED} for double buffering. When requesting RGB mode, highest bits per pixel mode will be selected. When requesting Index color mode, mode with highest number of colors will be selected. If all parameters are specified as zero, video adapter will try to figure out best possible mode and initialize it, platform specific differences are allowed here. If there is no mode matching request, error X will be returned. If there are no problems, function returns @code{GRUB_ERR_NONE}. + +This function also performs following task upon succesful mode switch. Active rendering target is changed to screen and viewport is maximized to allow whole screen to be used when performing graphics operations. In RGB modes, emulated palette gets 16 entries containing default values for VGA palette, other colors are defined as black. When switching to Indexed Color mode, driver may set default VGA palette to screen if the video card allows the operation. + +@end itemize + +@subsection grub_video_restore +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_restore (void); +@end example +@item Description: + +Video subsystem will deinitialize activated video driver to restore old state of video device. This can be used to switch back to text mode. +@end itemize + +@subsection grub_video_get_info +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_get_info (struct grub_video_mode_info *mode_info); +@end example +@example +struct grub_video_mode_info +@{ + /* Width of the screen. */ + unsigned int width; + /* Height of the screen. */ + unsigned int height; + /* Mode type bitmask. Contains information like is it Index color or + RGB mode. */ + unsigned int mode_type; + /* Bits per pixel. */ + unsigned int bpp; + /* Bytes per pixel. */ + unsigned int bytes_per_pixel; + /* Pitch of one scanline. How many bytes there are for scanline. */ + unsigned int pitch; + /* In index color mode, number of colors. In RGB mode this is 256. */ + unsigned int number_of_colors; + /* Optimization hint how binary data is coded. */ + enum grub_video_blit_format blit_format; + /* How many bits are reserved for red color. */ + unsigned int red_mask_size; + /* What is location of red color bits. In Index Color mode, this is 0. */ + unsigned int red_field_pos; + /* How many bits are reserved for green color. */ + unsigned int green_mask_size; + /* What is location of green color bits. In Index Color mode, this is 0. */ + unsigned int green_field_pos; + /* How many bits are reserved for blue color. */ + unsigned int blue_mask_size; + /* What is location of blue color bits. In Index Color mode, this is 0. */ + unsigned int blue_field_pos; + /* How many bits are reserved in color. */ + unsigned int reserved_mask_size; + /* What is location of reserved color bits. In Index Color mode, + this is 0. */ + unsigned int reserved_field_pos; +@}; +@end example +@item Description: + +Software developer can use this function to query properties of active rendering taget. Information provided here can be used by other parts of GRUB, like image loaders to convert loaded images to correct screen format to allow more optimized blitters to be used. If there there is no configured video driver with active screen, error @code{GRUB_ERR_BAD_DEVICE} is returned, otherwise @code{mode_info} is filled with valid information and @code{GRUB_ERR_NONE} is returned. +@end itemize + +@subsection grub_video_get_blit_format +@itemize +@item Prototype: + +@example +enum grub_video_blit_format +grub_video_get_blit_format (struct grub_video_mode_info *mode_info); +@end example +@example +enum grub_video_blit_format + @{ + /* Follow exactly field & mask information. */ + GRUB_VIDEO_BLIT_FORMAT_RGBA, + /* Make optimization assumption. */ + GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8, + /* Follow exactly field & mask information. */ + GRUB_VIDEO_BLIT_FORMAT_RGB, + /* Make optimization assumption. */ + GRUB_VIDEO_BLIT_FORMAT_R8G8B8, + /* When needed, decode color or just use value as is. */ + GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR + @}; +@end example +@item Description: + +Used to query how data could be optimized to suit specified video mode. Returns exact video format type, or a generic one if there is no definition for the type. For generic formats, use @code{grub_video_get_info} to query video color coding settings. +@end itemize + +@subsection grub_video_set_palette +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_set_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data); +@end example +@example +struct grub_video_palette_data +@{ + grub_uint8_t r; /* Red color value (0-255). */ + grub_uint8_t g; /* Green color value (0-255). */ + grub_uint8_t b; /* Blue color value (0-255). */ + grub_uint8_t a; /* Reserved bits value (0-255). */ +@}; +@end example +@item Description: + +Used to setup indexed color palettes. If mode is RGB mode, colors will be set to emulated palette data. In Indexed Color modes, palettes will be set to hardware. Color values will be converted to suit requirements of the video mode. @code{start} will tell what hardware color index (or emulated color index) will be set to according information in first indice of @code{palette_data}, after that both hardware color index and @code{palette_data} index will be incremented until @code{count} number of colors have been set. +@end itemize + +@subsection grub_video_get_palette +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_get_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data); +@end example +@example +struct grub_video_palette_data +@{ + grub_uint8_t r; /* Red color value (0-255). */ + grub_uint8_t g; /* Green color value (0-255). */ + grub_uint8_t b; /* Blue color value (0-255). */ + grub_uint8_t a; /* Reserved bits value (0-255). */ +@}; +@end example +@item Description: + +Used to query indexed color palettes. If mode is RGB mode, colors will be copied from emulated palette data. In Indexed Color modes, palettes will be read from hardware. Color values will be converted to suit structure format. @code{start} will tell what hardware color index (or emulated color index) will be used as a source for first indice of @code{palette_data}, after that both hardware color index and @code{palette_data} index will be incremented until @code{count} number of colors have been read. +@end itemize + +@subsection grub_video_set_viewport +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_set_viewport (unsigned int x, unsigned int y, unsigned int width, unsigned int height); +@end example +@item Description: + +Used to specify viewport where draw commands are performed. When viewport is set, all draw commands coordinates relate to those specified by @code{x} and @code{y}. If draw commands try to draw over viewport, they are clipped. If developer requests larger than possible viewport, width and height will be clamped to fit screen. If @code{x} and @code{y} are out of bounds, all functions drawing to screen will not be displayed. In order to maximize viewport, use @code{grub_video_get_info} to query actual screen dimensions and provide that information to this function. +@end itemize + +@subsection grub_video_get_viewport +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_get_viewport (unsigned int *x, unsigned int *y, unsigned int *width, unsigned int *height); +@end example +@item Description: + +Used to query current viewport dimensions. Software developer can use this to choose best way to render contents of the viewport. +@end itemize + +@subsection grub_video_map_color +@itemize +@item Prototype: + +@example +grub_video_color_t +grub_video_map_color (grub_uint32_t color_name); +@end example +@item Description: + +Map color can be used to support color themes in GRUB. There will be collection of color names that can be used to query actual screen mapped color data. Examples could be @code{GRUB_COLOR_CONSOLE_BACKGROUND}, @code{GRUB_COLOR_CONSOLE_TEXT}. The actual color defines are not specified at this point. +@end itemize + +@subsection grub_video_map_rgb +@itemize +@item Prototype: + +@example +grub_video_color_t +grub_video_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue); +@end example +@item Description: + +Map RGB values to compatible screen color data. Values are expected to be in range 0-255 and in RGB modes they will be converted to screen color data. In index color modes, index color palette will be searched for specified color and then index is returned. +@end itemize + +@subsection grub_video_map_rgba +@itemize +@item Prototype: + +@example +grub_video_color_t +grub_video_map_rgba (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue, grub_uint8_t alpha); +@end example +@item Description: + +Map RGBA values to compatible screen color data. Values are expected to be in range 0-255. In RGBA modes they will be converted to screen color data. In index color modes, index color palette will be searched for best matching color and its index is returned. +@end itemize + +@subsection grub_video_unmap_color +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_unmap_color (grub_video_color_t color, grub_uint8_t *red, grub_uint8_t *green, grub_uint8_t *blue, grub_uint8_t *alpha); +@end example +@item Description: + +Unmap color value from @code{color} to color channels in @code{red}, @code{green}, @code{blue} and @code{alpha}. Values will be in range 0-255. Active rendering target will be used for color domain. In case alpha information is not available in rendering target, it is assumed to be opaque (having value 255). +@end itemize + +@subsection grub_video_fill_rect +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_fill_rect (grub_video_color_t color, int x, int y, unsigned int width, unsigned int height); +@end example +@item Description: + +Fill specified area limited by given coordinates within specified viewport. Negative coordinates are accepted in order to allow easy moving of rectangle within viewport. If coordinates are negative, area of the rectangle will be shrinken to follow size limits of the viewport. + +Software developer should use either @code{grub_video_map_color}, @code{grub_video_map_rgb} or @code{grub_video_map_rgba} to map requested color to @code{color} parameter. +@end itemize + +@subsection grub_video_blit_glyph +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_blit_glyph (struct grub_font_glyph *glyph, grub_video_color_t color, int x, int y); +@end example +@example +struct grub_font_glyph @{ + /* TBD. */ +@}; +@end example +@item Description: + +Used to blit glyph to viewport in specified coodinates. If glyph is at edge of viewport, pixels outside of viewport will be clipped out. Software developer should use either @code{grub_video_map_rgb} or @code{grub_video_map_rgba} to map requested color to @code{color} parameter. +@end itemize + +@subsection grub_video_blit_bitmap +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_blit_bitmap (struct grub_video_bitmap *bitmap, enum grub_video_blit_operators oper, int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height); +@end example +@example +struct grub_video_bitmap +@{ + /* TBD. */ +@}; + +enum grub_video_blit_operators + @{ + GRUB_VIDEO_BLIT_REPLACE, + GRUB_VIDEO_BLIT_BLEND + @}; +@end example +@item Description: + +Used to blit bitmap to viewport in specified coordinates. If part of bitmap is outside of viewport region, it will be clipped out. Offsets affect bitmap position where data will be copied from. Negative values for both viewport coordinates and bitmap offset coordinates are allowed. If data is looked out of bounds of bitmap, color value will be assumed to be transparent. If viewport coordinates are negative, area of the blitted rectangle will be shrinken to follow size limits of the viewport and bitmap. Blitting operator @code{oper} specifies should source pixel replace data in screen or blend with pixel alpha value. + +Software developer should use @code{grub_video_bitmap_create} or @code{grub_video_bitmap_load} to create or load bitmap data. +@end itemize + +@subsection grub_video_blit_render_target +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_blit_render_target (struct grub_video_render_target *source, enum grub_video_blit_operators oper, int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height); +@end example +@example +struct grub_video_render_target @{ + /* This is private data for video driver. Should not be accessed from elsewhere directly. */ +@}; + +enum grub_video_blit_operators + @{ + GRUB_VIDEO_BLIT_REPLACE, + GRUB_VIDEO_BLIT_BLEND + @}; +@end example +@item Description: + +Used to blit source render target to viewport in specified coordinates. If part of source render target is outside of viewport region, it will be clipped out. If blitting operator is specified and source contains alpha values, resulting pixel color components will be calculated using formula ((src_color * src_alpha) + (dst_color * (255 - src_alpha)) / 255, if target buffer has alpha, it will be set to src_alpha. Offsets affect render target position where data will be copied from. If data is looked out of bounds of render target, color value will be assumed to be transparent. Blitting operator @code{oper} specifies should source pixel replace data in screen or blend with pixel alpha value. +@end itemize + +@subsection grub_video_scroll +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_scroll (grub_video_color_t color, int dx, int dy); +@end example +@item Description: + +Used to scroll viewport to specified direction. New areas are filled with specified color. This function is used when screen is scroller up in video terminal. +@end itemize + +@subsection grub_video_swap_buffers +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_swap_buffers (void); +@end example +@item Description: + +If double buffering is enabled, this swaps frontbuffer and backbuffer, in order to show values drawn to back buffer. Video driver is free to choose how this operation is techincally done. +@end itemize + +@subsection grub_video_create_render_target +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_create_render_target (struct grub_video_render_target **result, unsigned int width, unsigned int height, unsigned int mode_type); +@end example +@example +struct grub_video_render_target @{ + /* This is private data for video driver. Should not be accessed from elsewhere directly. */ +@}; +@end example +@item Description: + +Driver will use information provided to it to create best fitting render target. @code{mode_type} will be used to guide on selecting what features are wanted for render target. Supported values for @code{mode_type} are @code{GRUB_VIDEO_MODE_TYPE_INDEX_COLOR} for index color modes, @code{GRUB_VIDEO_MODE_TYPE_RGB} for direct RGB color modes and @code{GRUB_VIDEO_MODE_TYPE_ALPHA} for alpha component. +@end itemize + +@subsection grub_video_delete_render_target +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_delete_render_target (struct grub_video_render_target *target); +@end example +@item Description: + +Used to delete previously created render target. If @code{target} contains @code{NULL} pointer, nothing will be done. If render target is correctly destroyed, GRUB_ERR_NONE is returned. +@end itemize + +@subsection grub_video_set_active_render_target +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_set_active_render_target (struct grub_video_render_target *target); +@end example +@item Description: + +Sets active render target. If this comand is successful all drawing commands will be done to specified @code{target}. There is also special values for target, @code{GRUB_VIDEO_RENDER_TARGET_DISPLAY} used to reference screen's front buffer, @code{GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER} used to reference screen's front buffer (alias for @code{GRUB_VIDEO_RENDER_TARGET_DISPLAY}) and @code{GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER} used to reference back buffer (if double buffering is enabled). If render target is correclty switched GRUB_ERR_NONE is returned. In no any event shall there be non drawable active render target. + +@end itemize +@subsection grub_video_get_active_render_target +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_get_active_render_target (struct grub_video_render_target **target); +@end example +@item Description: + +Returns currently active render target. It returns value in @code{target} that can be subsequently issued back to @code{grub_video_set_active_render_target}. +@end itemize + +@node Example usage of Video API +@section Example usage of Video API +@subsection Example of screen setup +@example +grub_err_t rc; +/* Try to initialize video mode 1024 x 768 with direct RGB. */ +rc = grub_video_setup (1024, 768, GRUB_VIDEO_MODE_TYPE_RGB); +if (rc != GRUB_ERR_NONE) +@{ + /* Fall back to standard VGA Index Color mode. */ + rc = grub_video_setup (640, 480, GRUB_VIDEO_MODE_TYPE_INDEX); + if (rc != GRUB_ERR_NONE) + @{ + /* Handle error. */ + @} +@} +@end example +@subsection Example of setting up console viewport +@example +grub_uint32_t x, y, width, height; +grub_video_color_t color; +struct grub_font_glyph glyph; +grub_err_t rc; +/* Query existing viewport. */ +grub_video_get_viewport (&x, &y, &width, &height); +/* Fill background. */ +color = grub_video_map_color (GRUB_COLOR_BACKGROUND); +grub_video_fill_rect (color, 0, 0, width, height); +/* Setup console viewport. */ +grub_video_set_viewport (x + 10, y + 10, width - 20, height - 20); +grub_video_get_viewport (&x, &y, &width, &height); +color = grub_video_map_color (GRUB_COLOR_CONSOLE_BACKGROUND); +grub_video_fill_rect (color, 0, 0, width, height); +/* Draw text to viewport. */ +color = grub_video_map_color (GRUB_COLOR_CONSOLE_TEXT); +grub_font_get_glyph ('X', &glyph); +grub_video_blit_glyph (&glyph, color, 0, 0); +@end example + +@node Bitmap API +@section Bitmap API +@itemize +@subsection grub_video_bitmap_create +@item Prototype: +@example +grub_err_t grub_video_bitmap_create (struct grub_video_bitmap **bitmap, unsigned int width, unsigned int height, enum grub_video_blit_format blit_format) +@end example + +@item Description: + +Creates a new bitmap with given dimensions and blitting format. Allocated bitmap data can then be modified freely and finally blitted with @code{grub_video_blit_bitmap} to rendering target. +@end itemize + +@subsection grub_video_bitmap_destroy +@itemize +@item Prototype: +@example +grub_err_t grub_video_bitmap_destroy (struct grub_video_bitmap *bitmap); +@end example + +@item Description: + +When bitmap is no longer needed, it can be freed from memory using this command. @code{bitmap} is previously allocated bitmap with @code{grub_video_bitmap_create} or loaded with @code{grub_video_bitmap_load}. +@end itemize + +@subsection grub_video_bitmap_load +@itemize +@item Prototype: +@example +grub_err_t grub_video_bitmap_load (struct grub_video_bitmap **bitmap, const char *filename); +@end example + +@item Description: + +Tries to load given bitmap (@code{filename}) using registered bitmap loaders. In case bitmap format is not recognized or supported error @code{GRUB_ERR_BAD_FILE_TYPE} is returned. +@end itemize + +@subsection grub_video_bitmap_get_width +@itemize +@item Prototype: +@example +unsigned int grub_video_bitmap_get_width (struct grub_video_bitmap *bitmap); +@end example + +@item Description: + +Returns bitmap width. +@end itemize + +@subsection grub_video_bitmap_get_height +@itemize +@item Prototype: +@example +unsigned int grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap); +@end example + +@item Description: + +Return bitmap height. +@end itemize + +@subsection grub_video_bitmap_get_mode_info +@itemize +@item Prototype: +@example +void grub_video_bitmap_get_mode_info (struct grub_video_bitmap *bitmap, struct grub_video_mode_info *mode_info); +@end example + +@item Description: + +Returns bitmap format details in form of @code{grub_video_mode_info}. +@end itemize + +@subsection grub_video_bitmap_get_data +@itemize +@item Prototype: +@example +void *grub_video_bitmap_get_data (struct grub_video_bitmap *bitmap); +@end example + +@item Description: + +Return pointer to bitmap data. Contents of the pointed data can be freely modified. There is no extra protection against going off the bounds so you have to be carefull how to access the data. +@end itemize + +@node PFF2 Font File Format +@chapter PFF2 Font File Format + +@c Author: Colin D. Bennett +@c Date: 8 January 2009 + +@menu +* Introduction:: +* File Structure:: +* Font Metrics:: +@end menu + + +@node Introduction +@section Introduction + +The goal of this format is to provide a bitmap font format that is simple to +use, compact, and cleanly supports Unicode. + + +@subsection Goals of the GRUB Font Format + +@itemize +@item Simple to read and use. +Since GRUB will only be reading the font files, +we are more concerned with making the code to read the font simple than we +are with writing the font. + +@item Compact storage. +The fonts will generally be stored in a small boot +partition where GRUB is located, and this may be on a removable storage +device such as a CD or USB flash drive where space is more limited than it +is on most hard drives. + +@item Unicode. +GRUB should not have to deal with multiple character +encodings. The font should always use Unicode character codes for simple +internationalization. +@end itemize + +@subsection Why Another Font Format? + +There are many existing bitmap font formats that GRUB could use. However, +there are aspects of these formats that may make them less than suitable for +use in GRUB at this time: + +@table @samp +@item BDF +Inefficient storage; uses ASCII to describe properties and +hexadecimal numbers in ASCII for the bitmap rows. +@item PCF +Many format variations such as byte order and bitmap padding (rows +padded to byte, word, etc.) would result in more complex code to +handle the font format. +@end table + +@node File Structure +@section File Structure + +A file @strong{section} consists of a 4-byte name, a 32-bit big-endian length (not +including the name or length), and then @var{length} more section-type-specific +bytes. + +The standard file extension for PFF2 font files is @file{.pf2}. + + +@subsection Section Types + +@table @samp +@item FILE +@strong{File type ID} (ASCII string). This must be the first section in the file. It has length 4 +and the contents are the four bytes of the ASCII string @samp{PFF2}. + +@item NAME +@strong{Font name} (ASCII string). This is the full font name including family, +weight, style, and point size. For instance, "Helvetica Bold Italic 14". + +@item FAMI +@strong{Font family name} (ASCII string). For instance, "Helvetica". This should +be included so that intelligent font substitution can take place. + +@item WEIG +@strong{Font weight} (ASCII string). Valid values are @samp{bold} and @samp{normal}. +This should be included so that intelligent font substitution can take +place. + +@item SLAN +@strong{Font slant} (ASCII string). Valid values are @samp{italic} and @samp{normal}. +This should be included so that intelligent font substitution can take +place. + +@item PTSZ +@strong{Font point size} (uint16be). + +@item MAXW +@strong{Maximum character width in pixels} (uint16be). + +@item MAXH +@strong{Maximum character height in pixels} (uint16be). + +@item ASCE +@strong{Ascent in pixels} (uint16be). @xref{Font Metrics}, for details. + +@item DESC +@strong{Descent in pixels} (uint16be). @xref{Font Metrics}, for details. + +@item CHIX +@strong{Character index.} +The character index begins with a 32-bit big-endian unsigned integer +indicating the total size of the section, not including this size value. +For each character, there is an instance of the following entry structure: + +@itemize +@item @strong{Unicode code point.} (32-bit big-endian integer.) + +@item @strong{Storage flags.} (byte.) + +@itemize +@item Bits 2..0: + +If equal to 000 binary, then the character data is stored +uncompressed beginning at the offset indicated by the character's +@strong{offset} value. + +If equal to 001 binary, then the character data is stored within a +compressed character definition block that begins at the offset +within the file indicated by the character's @strong{offset} value. +@end itemize + +@item @strong{Offset.} (32-bit big-endian integer.) + +A marker that indicates the remainder of the file is data accessed via +the character index (CHIX) section. When reading this font file, the rest +of the file can be ignored when scanning the sections. The length should +be set to -1 (0xFFFFFFFF). + +Supported data structures: + +Character definition +Each character definition consists of: + +@itemize +@item @strong{Width.} +Width of the bitmap in pixels. The bitmap's extents +represent the glyph's bounding box. @code{uint16be}. + +@item @strong{Height.} +Height of the bitmap in pixels. The bitmap's extents +represent the glyph's bounding box. @code{uint16be}. + +@item @strong{X offset.} +The number of pixels to shift the bitmap by +horizontally before drawing the character. @code{int16be}. + +@item @strong{Y offset.} +The number of pixels to shift the bitmap by +vertically before drawing the character. @code{int16be}. + +@item @strong{Device width.} +The number of pixels to advance horizontally from +this character's origin to the origin of the next character. +@code{int16be}. + +@item @strong{Bitmap data.} +This is encoded as a string of bits. It is +organized as a row-major, top-down, left-to-right bitmap. The most +significant bit of each byte is taken to be the leftmost or uppermost +bit in the byte. For the sake of compact storage, rows are not padded +to byte boundaries (i.e., a single byte may contain bits belonging to +multiple rows). The last byte of the bitmap @strong{is} padded with zero +bits in the bits positions to the right of the last used bit if the +bitmap data does not fill the last byte. + +The length of the @strong{bitmap data} field is (@var{width} * @var{height} + 7) / 8 +using integer arithmetic, which is equivalent to ceil(@var{width} * +@var{height} / 8) using real number arithmetic. + +It remains to be determined whether bitmap fonts usually make all +glyph bitmaps the same height, or if smaller glyphs are stored with +bitmaps having a lesser height. In the latter case, the baseline +would have to be used to calculate the location the bitmap should be +anchored at on screen. +@end itemize + +@end itemize +@end table + +@node Font Metrics +@section Font Metrics + +@itemize +@item Ascent. +The distance from the baseline to the top of most characters. +Note that in some cases characters may extend above the ascent. + +@item Descent. +The distance from the baseline to the bottom of most characters. Note that +in some cases characters may extend below the descent. + +@item Leading. +The amount of space, in pixels, to leave between the descent of one line of +text and the ascent of the next line. This metrics is not specified in the +current file format; instead, the font rendering engine calculates a +reasonable leading value based on the other font metrics. + +@item Horizonal leading. +The amount of space, in pixels, to leave horizontally between the left and +right edges of two adjacent glyphs. The @strong{device width} field determines +the effective leading value that is used to render the font. + +@end itemize +@image{font_char_metrics,,,,.png} + +An illustration of how the various font metrics apply to characters. + + + +@node Graphical Menu Software Design +@chapter Graphical Menu Software Design + +@c By Colin D. Bennett +@c Date: 17 August 2008 + +@menu +* Introduction_2:: +* Startup Sequence:: +* GUI Components:: +* Command Line Window:: +@end menu + +@node Introduction_2 +@section Introduction + +The @samp{gfxmenu} module provides a graphical menu interface for GRUB 2. It +functions as an alternative to the menu interface provided by the @samp{normal} +module, which uses the grub terminal interface to display a menu on a +character-oriented terminal. + +The graphical menu uses the GRUB video API, which is currently for the VESA +BIOS extensions (VBE) 2.0+. This is supported on the i386-pc platform. +However, the graphical menu itself does not depend on using VBE, so if another +GRUB video driver were implemented, the @samp{gfxmenu} graphical menu would work +on the new video driver as well. + + +@node Startup Sequence +@section Startup Sequence + +@itemize +@item grub_enter_normal_mode [normal/main.c] +@item grub_normal_execute [normal/main.c] +@item read_config_file [normal/main.c] +@item (When @file{gfxmenu.mod} is loaded with @command{insmod}, it will call @code{grub_menu_viewer_register()} to register itself.) +@item GRUB_MOD_INIT (gfxmenu) [gfxmenu/gfxmenu.c] +@item grub_menu_viewer_register [kern/menu_viewer.c] +@item grub_menu_viewer_show_menu [kern/menu_viewer.c] +@item get_current_menu_viewer() [kern/menu_viewer.c] +@item show_menu() [gfxmenu/gfxmenu.c] +@item grub_gfxmenu_model_new [gfxmenu/model.c] +@item grub_gfxmenu_view_new [gfxmenu/view.c] +@item set_graphics_mode [gfxmenu/view.c] +@item grub_gfxmenu_view_load_theme [gfxmenu/theme_loader.c] +@end itemize + + +@node GUI Components +@section GUI Components + +The graphical menu implements a GUI component system that supports a +container-based layout system. Components can be added to containers, and +containers (which are a type of component) can then be added to other +containers, to form a tree of components. Currently, the root component of +this tree is a @samp{canvas} component, which allows manual layout of its child +components. + +Components (non-container): + +@itemize +@item label +@item image +@item progress_bar +@item circular_progress +@item list (currently hard coded to be a boot menu list) +@end itemize + +Containers: + +@itemize +@item canvas +@item hbox +@item vbox +@end itemize + +The GUI component instances are created by the theme loader in +@file{gfxmenu/theme_loader.c} when a theme is loaded. Theme files specify +statements such as @samp{+vbox@{ +label @{ text="Hello" @} +label@{ text="World" @} @}} +to add components to the component tree root. By nesting the component +creation statements in the theme file, the instantiated components are nested +the same way. + +When a component is added to a container, that new child is considered @strong{owned} +by the container. Great care should be taken if the caller retains a +reference to the child component, since it will be destroyed if its parent +container is destroyed. A better choice instead of storing a pointer to the +child component is to use the component ID to find the desired component. +Component IDs do not have to be unique (it is often useful to have multiple +components with an ID of "__timeout__", for instance). + +In order to access and use components in the component tree, there are two +functions (defined in @file{gfxmenu/gui_util.c}) that are particularly useful: + +@itemize + +@item @code{grub_gui_find_by_id (root, id, callback, userdata)}: + +This function ecursively traverses the component tree rooted at @var{root}, and +for every component that has an ID equal to @var{id}, calls the function pointed +to by @var{callback} with the matching component and the void pointer @var{userdata} +as arguments. The callback function can do whatever is desired to use the +component passed in. + +@item @code{grub_gui_iterate_recursively (root, callback, userdata)}: + +This function calls the function pointed to by @var{callback} for every +component that is a descendant of @var{root} in the component tree. When the +callback function is called, the component and the void pointer @var{userdata} +as arguments. The callback function can do whatever is desired to use the +component passed in. +@end itemize + +@node Command Line Window +@section Command Line Window + +The terminal window used to provide command line access within the graphical +menu is managed by @file{gfxmenu/view.c}. The @samp{gfxterm} terminal is used, and +it has been modified to allow rendering to an offscreen render target to allow +it to be composed into the double buffering system that the graphical menu +view uses. This is bad for performance, however, so it would probably be a +good idea to make it possible to temporarily disable double buffering as long +as the terminal window is visible. There are still unresolved problems that +occur when commands are executed from the terminal window that change the +graphics mode. It's possible that making @code{grub_video_restore()} return to +the graphics mode that was in use before @code{grub_video_setup()} was called +might fix some of the problems. + + +@node Copying This Manual +@appendix Copying This Manual + +@menu +* GNU Free Documentation License:: License for copying this manual. +@end menu + +@include fdl.texi + + +@node Index +@unnumbered Index + +@c Currently, we use only the Concept Index. +@printindex cp + +@bye diff --git a/docs/grub.texi b/docs/grub.texi index 0808ded6b..95707e4cc 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -100,7 +100,6 @@ This edition documents version @value{VERSION}. * Obtaining and Building GRUB:: How to obtain and build GRUB * Reporting bugs:: Where you should send a bug report * Future:: Some future plans on GRUB -* Internals:: Hacking GRUB * Copying This Manual:: Copying This Manual * Index:: @end menu @@ -1487,14 +1486,14 @@ reside anywhere on the file system, and may be removed after running @command{grub-mkimage}. After the embedded configuration file (if any) is executed, GRUB will load -the @samp{normal} module, which will then read the real configuration file -from @file{$prefix/grub.cfg}. By this point, the @code{root} variable will -also have been set to the root device name. For example, @code{prefix} -might be set to @samp{(hd0,1)/boot/grub}, and @code{root} might be set to -@samp{hd0,1}. Thus, in most cases, the embedded configuration file only -needs to set the @code{prefix} and @code{root} variables, and then drop -through to GRUB's normal processing. A typical example of this might look -like this: +the @samp{normal} module (@pxref{normal}), which will then read the real +configuration file from @file{$prefix/grub.cfg}. By this point, the +@code{root} variable will also have been set to the root device name. For +example, @code{prefix} might be set to @samp{(hd0,1)/boot/grub}, and +@code{root} might be set to @samp{hd0,1}. Thus, in most cases, the embedded +configuration file only needs to set the @code{prefix} and @code{root} +variables, and then drop through to GRUB's normal processing. A typical +example of this might look like this: @example @group @@ -2050,6 +2049,44 @@ model-specific. Values known to the GRUB team are: To take full advantage of this function, install GRUB into the MBR (@pxref{Installing GRUB using grub-install}). +If you have a laptop which has a similar feature and not in the above list +could you figure your address and contribute? +To discover the address do the following: +@itemize +@item boot normally +@item +@example +sudo modprobe nvram +sudo cat /dev/nvram | xxd > normal_button.txt +@end example +@item boot using vendor button +@item +@example +sudo modprobe nvram +sudo cat /dev/nvram | xxd > normal_vendor.txt +@end example +@end itemize + +Then compare these text files and find where a bit was toggled. E.g. in +case of Dell XPS it was: +@example +byte 0x47: 20 --> 28 +@end example +It's a bit number 3 as seen from following table: +@multitable @columnfractions .2 .2 +@item 0 @tab 01 +@item 1 @tab 02 +@item 2 @tab 04 +@item 3 @tab 08 +@item 4 @tab 10 +@item 5 @tab 20 +@item 6 @tab 40 +@item 7 @tab 80 +@end multitable + +0x47 is decimal 71. Linux nvram implementation cuts first 14 bytes of +CMOS. So the real byte address in CMOS is 71+14=85 +So complete address is 85:3 @node Images @chapter GRUB image files @@ -3052,6 +3089,8 @@ you forget a command, you can run the command @command{help} * load_env:: Load variables from environment block * loopback:: Make a device from a filesystem image * ls:: List devices or files +* normal:: Enter normal mode +* normal_exit:: Exit from normal mode * parttool:: Modify partition table entries * password:: Set a clear-text password * password_pbkdf2:: Set a hashed password @@ -3508,6 +3547,34 @@ name syntax}), then list the contents of that directory. @end deffn +@node normal +@subsection normal + +@deffn Command normal [file] +Enter normal mode and display the GRUB menu. + +In normal mode, commands, filesystem modules, and cryptography modules are +automatically loaded, and the full GRUB script parser is available. Other +modules may be explicitly loaded using @command{insmod} (@pxref{insmod}). + +If a @var{file} is given, then commands will be read from that file. +Otherwise, they will be read from @file{$prefix/grub.cfg} if it exists. + +@command{normal} may be called from within normal mode, creating a nested +environment. It is more usual to use @command{configfile} +(@pxref{configfile}) for this. +@end deffn + + +@node normal_exit +@subsection normal_exit + +@deffn Command normal_exit +Exit normal mode (@pxref{normal}). If this instance of normal mode was not +nested within another one, then return to rescue mode. +@end deffn + + @node parttool @subsection parttool @@ -4045,7 +4112,7 @@ GRUB's normal start-up procedure involves setting the @samp{prefix} environment variable to a value set in the core image by @command{grub-install}, setting the @samp{root} variable to match, loading the @samp{normal} module from the prefix, and running the @samp{normal} -command. This command is responsible for reading +command (@pxref{normal}). This command is responsible for reading @file{/boot/grub/grub.cfg}, running the menu, and doing all the useful things GRUB is supposed to do. @@ -4060,6 +4127,8 @@ device), then you can correct this and enter normal mode manually: @group # Inspect the current prefix (and other preset variables): set +# Find out which devices are available: +ls # Set to the correct value, which might be something like this: set prefix=(hd0,1)/grub set root=(hd0,1) @@ -4374,111 +4443,6 @@ If you are interested in the development of GRUB 2, take a look at @uref{http://www.gnu.org/software/grub/grub.html, the homepage}. -@node Internals -@appendix Hacking GRUB - -@menu -* Getting the source code:: -* Finding your way around:: -@end menu - - -@node Getting the source code -@section Getting the source code - -GRUB is maintained using the @uref{http://bazaar-vcs.org/, Bazaar revision -control system}. To fetch the primary development branch: - -@example -bzr get http://bzr.savannah.gnu.org/r/grub/trunk/grub -@end example - -The GRUB developers maintain several other branches with work in progress. -Of these, the most interesting is the experimental branch, which is a -staging area for new code which we expect to eventually merge into trunk but -which is not yet ready: - -@example -bzr get http://bzr.savannah.gnu.org/r/grub/branches/experimental -@end example - -Once you have used @kbd{bzr get} to fetch an initial copy of a branch, you -can use @kbd{bzr pull} to keep it up to date. If you have modified your -local version, you may need to resolve conflicts when pulling. - - -@node Finding your way around -@section Finding your way around - -Here is a brief map of the GRUB code base. - -GRUB uses Autoconf, but not (yet) Automake. The top-level build rules are -in @file{configure.ac}, @file{Makefile.in}, and @file{conf/*.rmk}. Each -@file{conf/*.rmk} file represents a particular target configuration, and is -processed into GNU Make rules by @file{genmk.rb} (which you only need to -look at if you are extending the build system). If you are adding a new -module which follows an existing pattern, such as a new command or a new -filesystem implementation, it is usually easiest to grep @file{conf/*.rmk} -for an existing example of that pattern to find out where it should be -added. - -Low-level boot code, such as the MBR implementation on PC BIOS systems, is -in the @file{boot/} directory. - -The GRUB kernel is in @file{kern/}. This contains core facilities such as -the device, disk, and file frameworks, environment variable handling, list -processing, and so on. The kernel should contain enough to get up to a -rescue prompt. Header files for kernel facilities, among others, are in -@file{include/}. - -Terminal implementations are in @file{term/}. - -Disk access code is spread across @file{disk/} (for accessing the disk -devices themselves), @file{partmap/} (for interpreting partition table -data), and @file{fs/} (for accessing filesystems). Note that, with the odd -specialised exception, GRUB only contains code to @emph{read} from -filesystems and tries to avoid containing any code to @emph{write} to -filesystems; this lets us confidently assure users that GRUB cannot be -responsible for filesystem corruption. - -PCI and USB bus handling is in @file{bus/}. - -Video handling code is in @file{video/}. The graphical menu system uses -this heavily, but is in a separate directory, @file{gfxmenu/}. - -Most commands are implemented by files in @file{commands/}, with the -following exceptions: - -@itemize -@item -A few core commands live in @file{kern/corecmd.c}. - -@item -Commands related to normal mode live under @file{normal/}. - -@item -Commands that load and boot kernels live under @file{loader/}. - -@item -The @samp{loopback} command is really a disk device, and so lives in -@file{disk/loopback.c}. - -@item -The @samp{gettext} command lives under @file{gettext/}. - -@item -The @samp{loadfont} and @samp{lsfonts} commands live under @file{font/}. - -@item -The @samp{serial}, @samp{terminfo}, and @samp{background_image} commands -live under @file{term/}. - -@item -The @samp{efiemu_*} commands live under @file{efiemu/}. -@end itemize - -There are a few other special-purpose exceptions; grep for them if they -matter to you. diff --git a/docs/man/grub-editenv.h2m b/docs/man/grub-editenv.h2m index efbd79070..3859d3d4c 100644 --- a/docs/man/grub-editenv.h2m +++ b/docs/man/grub-editenv.h2m @@ -1,2 +1,5 @@ [NAME] grub-editenv \- edit GRUB environment block +[SEE ALSO] +.BR grub-reboot (8), +.BR grub-set-default (8) diff --git a/docs/man/grub-emu.h2m b/docs/man/grub-emu.h2m index 09a1f88c1..ef1c00065 100644 --- a/docs/man/grub-emu.h2m +++ b/docs/man/grub-emu.h2m @@ -1,2 +1,6 @@ [NAME] grub-emu \- GRUB emulator +[SEE ALSO] +If you are trying to install GRUB, then you should use +.BR grub-install (8) +rather than this program. diff --git a/docs/man/grub-fstest.h2m b/docs/man/grub-fstest.h2m index be39429b5..9676b159a 100644 --- a/docs/man/grub-fstest.h2m +++ b/docs/man/grub-fstest.h2m @@ -1,2 +1,4 @@ [NAME] grub-fstest \- debug tool for GRUB filesystem drivers +[SEE ALSO] +.BR grub-probe (8) diff --git a/docs/man/grub-install.h2m b/docs/man/grub-install.h2m index 65252155c..2de371a3f 100644 --- a/docs/man/grub-install.h2m +++ b/docs/man/grub-install.h2m @@ -1,2 +1,7 @@ [NAME] grub-install \- install GRUB to a device +[SEE ALSO] +.BR grub-mkconfig (8), +.BR grub-mkimage (1), +.BR grub-setup (8), +.BR grub-mkrescue (1) diff --git a/docs/man/grub-macho2img.h2m b/docs/man/grub-macho2img.h2m index 412bf926a..d79aaeed8 100644 --- a/docs/man/grub-macho2img.h2m +++ b/docs/man/grub-macho2img.h2m @@ -1,2 +1,4 @@ [NAME] grub-macho2img \- convert Mach-O to raw image +[SEE ALSO] +.BR grub-mkimage (1) diff --git a/docs/man/grub-menulst2cfg.h2m b/docs/man/grub-menulst2cfg.h2m index 0c0570f27..c2e0055ed 100644 --- a/docs/man/grub-menulst2cfg.h2m +++ b/docs/man/grub-menulst2cfg.h2m @@ -1,3 +1,4 @@ [NAME] grub-menulst2cfg \- transform legacy menu.lst into grub.cfg - +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-mkconfig.h2m b/docs/man/grub-mkconfig.h2m index b0d33ec61..9b42f8130 100644 --- a/docs/man/grub-mkconfig.h2m +++ b/docs/man/grub-mkconfig.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkconfig \- generate a GRUB configuration file +[SEE ALSO] +.BR grub-install (8) diff --git a/docs/man/grub-mkdevicemap.h2m b/docs/man/grub-mkdevicemap.h2m index 8ab34ac86..3ef8e9712 100644 --- a/docs/man/grub-mkdevicemap.h2m +++ b/docs/man/grub-mkdevicemap.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkdevicemap \- generate a GRUB device map file automatically +[SEE ALSO] +.BR grub-install (8) diff --git a/docs/man/grub-mkfont.h2m b/docs/man/grub-mkfont.h2m index d8580186f..d46fe600e 100644 --- a/docs/man/grub-mkfont.h2m +++ b/docs/man/grub-mkfont.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkfont \- make GRUB font files +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-mkimage.h2m b/docs/man/grub-mkimage.h2m index 71f270940..ca08b0c5c 100644 --- a/docs/man/grub-mkimage.h2m +++ b/docs/man/grub-mkimage.h2m @@ -1,2 +1,7 @@ [NAME] grub-mkimage \- make a bootable image of GRUB +[SEE ALSO] +.BR grub-install (8), +.BR grub-setup (8), +.BR grub-mkrescue (1), +.BR grub-mknetdir (8) diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m index e0ae9dedb..cda6f3676 100644 --- a/docs/man/grub-mklayout.h2m +++ b/docs/man/grub-mklayout.h2m @@ -1,2 +1,4 @@ [NAME] grub-mklayout \- generate a GRUB keyboard layout file +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-mknetdir.h2m b/docs/man/grub-mknetdir.h2m index 26defe876..a2ef13ec1 100644 --- a/docs/man/grub-mknetdir.h2m +++ b/docs/man/grub-mknetdir.h2m @@ -1,2 +1,4 @@ [NAME] grub-mknetdir \- prepare a GRUB netboot directory. +[SEE ALSO] +.BR grub-mkimage (1) diff --git a/docs/man/grub-mkpasswd-pbkdf2.h2m b/docs/man/grub-mkpasswd-pbkdf2.h2m index 5b2b2ef7f..4d202f3da 100644 --- a/docs/man/grub-mkpasswd-pbkdf2.h2m +++ b/docs/man/grub-mkpasswd-pbkdf2.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkpasswd-pbkdf2 \- generate hashed password for GRUB +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-mkrelpath.h2m b/docs/man/grub-mkrelpath.h2m index ccc0880fa..d01f3961e 100644 --- a/docs/man/grub-mkrelpath.h2m +++ b/docs/man/grub-mkrelpath.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkrelpath \- make a system path relative to its root +[SEE ALSO] +.BR grub-probe (8) diff --git a/docs/man/grub-mkrescue.h2m b/docs/man/grub-mkrescue.h2m index 5e92e0d99..a427f02e3 100644 --- a/docs/man/grub-mkrescue.h2m +++ b/docs/man/grub-mkrescue.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkrescue \- make a GRUB rescue image +[SEE ALSO] +.BR grub-mkimage (1) diff --git a/docs/man/grub-ofpathname.h2m b/docs/man/grub-ofpathname.h2m index f07158cb3..74b43eea0 100644 --- a/docs/man/grub-ofpathname.h2m +++ b/docs/man/grub-ofpathname.h2m @@ -1,2 +1,4 @@ [NAME] grub-ofpathname \- find OpenBOOT path for a device +[SEE ALSO] +.BR grub-probe (8) diff --git a/docs/man/grub-pe2elf.h2m b/docs/man/grub-pe2elf.h2m index 3fdb88b43..7ca29bd70 100644 --- a/docs/man/grub-pe2elf.h2m +++ b/docs/man/grub-pe2elf.h2m @@ -1,2 +1,4 @@ [NAME] grub-pe2elf \- convert PE image to ELF +[SEE ALSO] +.BR grub-mkimage (1) diff --git a/docs/man/grub-probe.h2m b/docs/man/grub-probe.h2m index 817ba8ef6..6e1ffdcf9 100644 --- a/docs/man/grub-probe.h2m +++ b/docs/man/grub-probe.h2m @@ -1,2 +1,4 @@ [NAME] grub-probe \- probe device information for GRUB +[SEE ALSO] +.BR grub-fstest (1) diff --git a/docs/man/grub-reboot.h2m b/docs/man/grub-reboot.h2m index 957e4b797..e4acace65 100644 --- a/docs/man/grub-reboot.h2m +++ b/docs/man/grub-reboot.h2m @@ -1,2 +1,5 @@ [NAME] grub-reboot \- set the default boot entry for GRUB, for the next boot only +[SEE ALSO] +.BR grub-set-default (8), +.BR grub-editenv (1) diff --git a/docs/man/grub-script-check.h2m b/docs/man/grub-script-check.h2m index 39c0a3ef6..365368267 100644 --- a/docs/man/grub-script-check.h2m +++ b/docs/man/grub-script-check.h2m @@ -1,2 +1,4 @@ [NAME] grub-script-check \- check grub.cfg for syntax errors +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-set-default.h2m b/docs/man/grub-set-default.h2m index dd0793cfd..7945001c1 100644 --- a/docs/man/grub-set-default.h2m +++ b/docs/man/grub-set-default.h2m @@ -1,2 +1,5 @@ [NAME] grub-set-default \- set the saved default boot entry for GRUB +[SEE ALSO] +.BR grub-reboot (8), +.BR grub-editenv (1) diff --git a/docs/man/grub-setup.h2m b/docs/man/grub-setup.h2m index e70e465a4..eebe3ef38 100644 --- a/docs/man/grub-setup.h2m +++ b/docs/man/grub-setup.h2m @@ -1,2 +1,6 @@ [NAME] grub-setup \- set up a device to boot using GRUB +[SEE ALSO] +.BR grub-install (8), +.BR grub-mkimage (1), +.BR grub-mkrescue (1) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 339185765..e242d8ece 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -906,6 +906,7 @@ module = { module = { name = btrfs; common = fs/btrfs.c; + common = lib/crc.c; }; module = { diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 425458401..9e81df192 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -120,7 +120,7 @@ __start: ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 lui $a0, %hi(unimplemented_memory_type) bne $t0, $v0, fatal - addiu $a0, $a0, %hi(unimplemented_memory_type) + addiu $a0, $a0, %lo(unimplemented_memory_type) /* And here is our goal: DDR2 controller initialisation. */ lui $t0, %hi(GRUB_CPU_LOONGSON_CORECFG) diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index 088f4dfc1..fbcb83cfe 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -22,6 +22,10 @@ #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + int grub_cs5536_find (grub_pci_device_t *devp) { diff --git a/grub-core/bus/pci.c b/grub-core/bus/pci.c index 11101d42b..07d20e3f5 100644 --- a/grub-core/bus/pci.c +++ b/grub-core/bus/pci.c @@ -21,6 +21,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* FIXME: correctly support 64-bit architectures. */ /* #if GRUB_TARGET_SIZEOF_VOID_P == 4 */ struct grub_pci_dma_chunk * diff --git a/grub-core/bus/usb/emu/usb.c b/grub-core/bus/usb/emu/usb.c index 7d52decb2..38c5f01f1 100644 --- a/grub-core/bus/usb/emu/usb.c +++ b/grub-core/bus/usb/emu/usb.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static struct grub_usb_controller_dev usb_controller = { diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index 8adaee6e0..df0d0f4af 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -29,6 +29,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_ohci_hcca { /* Pointers to Interrupt Endpoint Descriptors. Not used by diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c index ee8794de0..55d1884cc 100644 --- a/grub-core/bus/usb/serial/common.c +++ b/grub-core/bus/usb/serial/common.c @@ -18,6 +18,9 @@ #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); void grub_usbserial_fini (struct grub_serial_port *port) diff --git a/grub-core/bus/usb/serial/ftdi.c b/grub-core/bus/usb/serial/ftdi.c index bd1713b27..07ac7ac52 100644 --- a/grub-core/bus/usb/serial/ftdi.c +++ b/grub-core/bus/usb/serial/ftdi.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + enum { GRUB_FTDI_MODEM_CTRL = 0x01, diff --git a/grub-core/bus/usb/serial/pl2303.c b/grub-core/bus/usb/serial/pl2303.c index 9e3b9ae7e..b9954116b 100644 --- a/grub-core/bus/usb/serial/pl2303.c +++ b/grub-core/bus/usb/serial/pl2303.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* Convert speed to divisor. */ static grub_uint32_t is_speed_supported (unsigned int speed) diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c index 71142846b..99e597f6d 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_UHCI_IOMASK (0x7FF << 5) #define N_QH 256 diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c index 70173b7ea..005d3bcf0 100644 --- a/grub-core/bus/usb/usb.c +++ b/grub-core/bus/usb/usb.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_usb_controller_dev_t grub_usb_list; static struct grub_usb_attach_desc *attach_hooks; diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index 4f03997e0..8f4429627 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -33,6 +33,8 @@ #include #endif +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"exclude", 'x', 0, N_("Don't load host tables specified by comma-separated list."), diff --git a/grub-core/commands/blocklist.c b/grub-core/commands/blocklist.c index 4651fb32a..5eb12e434 100644 --- a/grub-core/commands/blocklist.c +++ b/grub-core/commands/blocklist.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c index 1ec1e6f77..7714011bf 100644 --- a/grub-core/commands/boot.c +++ b/grub-core/commands/boot.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t (*grub_loader_boot_func) (void); static grub_err_t (*grub_loader_unload_func) (void); static int grub_loader_noreturn; diff --git a/grub-core/commands/cat.c b/grub-core/commands/cat.c index 79ecf75c7..9be6cbc8f 100644 --- a/grub-core/commands/cat.c +++ b/grub-core/commands/cat.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"dos", -1, 0, N_("Accept DOS-style CR/NL line endings."), 0, 0}, diff --git a/grub-core/commands/cmp.c b/grub-core/commands/cmp.c index d9e76a4d7..0222927b6 100644 --- a/grub-core/commands/cmp.c +++ b/grub-core/commands/cmp.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define BUFFER_SIZE 512 static grub_err_t diff --git a/grub-core/commands/configfile.c b/grub-core/commands/configfile.c index 2568b7ee6..124a09a9e 100644 --- a/grub-core/commands/configfile.c +++ b/grub-core/commands/configfile.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_source (grub_command_t cmd, int argc, char **args) { diff --git a/grub-core/commands/date.c b/grub-core/commands/date.c index 623db4943..d27162077 100644 --- a/grub-core/commands/date.c +++ b/grub-core/commands/date.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_DATETIME_SET_YEAR 1 #define GRUB_DATETIME_SET_MONTH 2 #define GRUB_DATETIME_SET_DAY 4 diff --git a/grub-core/commands/echo.c b/grub-core/commands/echo.c index 93a452fc8..81ba50d68 100644 --- a/grub-core/commands/echo.c +++ b/grub-core/commands/echo.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {0, 'n', 0, N_("Do not output the trailing newline."), 0, 0}, diff --git a/grub-core/commands/efi/fixvideo.c b/grub-core/commands/efi/fixvideo.c index 6430be5e3..c53e47d8a 100644 --- a/grub-core/commands/efi/fixvideo.c +++ b/grub-core/commands/efi/fixvideo.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static struct grub_video_patch { const char *name; diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c index 8c7c25abd..138311222 100644 --- a/grub-core/commands/efi/loadbios.c +++ b/grub-core/commands/efi/loadbios.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID; static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID; static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID; diff --git a/grub-core/commands/efi/lsefimmap.c b/grub-core/commands/efi/lsefimmap.c index 2bb5dcb5d..215b45bff 100644 --- a/grub-core/commands/efi/lsefimmap.c +++ b/grub-core/commands/efi/lsefimmap.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define ADD_MEMORY_DESCRIPTOR(desc, size) \ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c index aa3e05aee..b2359253a 100644 --- a/grub-core/commands/efi/lsefisystab.c +++ b/grub-core/commands/efi/lsefisystab.c @@ -18,12 +18,15 @@ */ #include #include +#include #include #include #include #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct guid_mapping { grub_efi_guid_t guid; diff --git a/grub-core/commands/efi/lssal.c b/grub-core/commands/efi/lssal.c index 2ee993033..fa8005b88 100644 --- a/grub-core/commands/efi/lssal.c +++ b/grub-core/commands/efi/lssal.c @@ -23,6 +23,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); static void disp_sal (void *table) diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c index e9274fbab..69574e2b0 100644 --- a/grub-core/commands/extcmd.c +++ b/grub-core/commands/extcmd.c @@ -22,6 +22,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); grub_err_t grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, diff --git a/grub-core/commands/gptsync.c b/grub-core/commands/gptsync.c index 6364c13f7..e92dc20ec 100644 --- a/grub-core/commands/gptsync.c +++ b/grub-core/commands/gptsync.c @@ -29,6 +29,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* Convert a LBA address to a CHS address in the INT 13 format. */ /* Taken from grub1. */ /* XXX: use hardcoded geometry of C = 1024, H = 255, S = 63. diff --git a/grub-core/commands/halt.c b/grub-core/commands/halt.c index 3400115a0..317f7753f 100644 --- a/grub-core/commands/halt.c +++ b/grub-core/commands/halt.c @@ -22,6 +22,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c index 664fe9c24..6825d4811 100644 --- a/grub-core/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"hash", 'h', 0, N_("Specify hash to use."), N_("HASH"), ARG_TYPE_STRING}, {"check", 'c', 0, N_("Check hash list file."), N_("FILE"), ARG_TYPE_STRING}, diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c index b6ab78755..0c12b8814 100644 --- a/grub-core/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"apm", 'B', 0, N_("Set Advanced Power Management\n" "(1=low, ..., 254=high, 255=off)."), diff --git a/grub-core/commands/help.c b/grub-core/commands/help.c index ff6d7ed2e..82f3200c7 100644 --- a/grub-core/commands/help.c +++ b/grub-core/commands/help.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, char **args) diff --git a/grub-core/commands/hexdump.c b/grub-core/commands/hexdump.c index 629f2a069..9ba83598a 100644 --- a/grub-core/commands/hexdump.c +++ b/grub-core/commands/hexdump.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"skip", 's', 0, N_("Skip offset bytes from the beginning of file."), 0, ARG_TYPE_INT}, diff --git a/grub-core/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c index 994da11b0..c79bd0387 100644 --- a/grub-core/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -21,6 +21,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t parse_args (int argc, char *argv[], int *byte, int *bit) { diff --git a/grub-core/commands/i386/cpuid.c b/grub-core/commands/i386/cpuid.c index f5f0f15a8..6a771ba74 100644 --- a/grub-core/commands/i386/cpuid.c +++ b/grub-core/commands/i386/cpuid.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define cpuid(num,a,b,c,d) \ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index ed4211cca..c9c8881b4 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -29,6 +29,7 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13); diff --git a/grub-core/commands/i386/pc/halt.c b/grub-core/commands/i386/pc/halt.c index 81eb6a1bb..e7c191de3 100644 --- a/grub-core/commands/i386/pc/halt.c +++ b/grub-core/commands/i386/pc/halt.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"no-apm", 'n', 0, N_("Do not use APM to halt the computer."), 0, 0}, diff --git a/grub-core/commands/i386/pc/lsapm.c b/grub-core/commands/i386/pc/lsapm.c index 30475d2ec..17bcfd6eb 100644 --- a/grub-core/commands/i386/pc/lsapm.c +++ b/grub-core/commands/i386/pc/lsapm.c @@ -22,6 +22,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + int grub_apm_get_info (struct grub_apm_info *info) { diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c index 4ed937d4a..57980eb92 100644 --- a/grub-core/commands/i386/pc/play.c +++ b/grub-core/commands/i386/pc/play.c @@ -29,6 +29,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define BASE_TEMPO (60 * GRUB_TICKS_PER_SECOND) /* The speaker port. */ diff --git a/grub-core/commands/i386/pc/pxecmd.c b/grub-core/commands/i386/pc/pxecmd.c index b576a8ea4..dffa15a3a 100644 --- a/grub-core/commands/i386/pc/pxecmd.c +++ b/grub-core/commands/i386/pc/pxecmd.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index c777ea60a..a55d17bd0 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv2+"); + static char sendkey[0x20]; /* Length of sendkey. */ static int keylen = 0; diff --git a/grub-core/commands/ieee1275/suspend.c b/grub-core/commands/ieee1275/suspend.c index f096cc9ba..de068951d 100644 --- a/grub-core/commands/ieee1275/suspend.c +++ b/grub-core/commands/ieee1275/suspend.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_suspend (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c index 20d203e92..e7035b528 100644 --- a/grub-core/commands/iorw.c +++ b/grub-core/commands/iorw.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_extcmd_t cmd_read_byte, cmd_read_word, cmd_read_dword; static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword; diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c index deb482a85..6c5913a54 100644 --- a/grub-core/commands/keylayouts.c +++ b/grub-core/commands/keylayouts.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static struct grub_keyboard_layout layout_us = { .keyboard_map = { /* Keyboard errors. Handled by driver. */ diff --git a/grub-core/commands/keystatus.c b/grub-core/commands/keystatus.c index 9e1486c9d..f3a669942 100644 --- a/grub-core/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"shift", 's', 0, N_("Check Shift key."), 0, 0}, diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 23c1c1908..e68b3315a 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -33,6 +33,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t legacy_file (const char *filename) { diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c index 38b3a84c6..5d53a8e66 100644 --- a/grub-core/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME}, diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 9bccda349..20a75733c 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -33,6 +33,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"long", 'l', 0, N_("Show a long list with more detailed information."), 0, 0}, diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c index 64b559665..fd19e380a 100644 --- a/grub-core/commands/lsacpi.c +++ b/grub-core/commands/lsacpi.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static void print_strn (grub_uint8_t *str, grub_size_t len) { diff --git a/grub-core/commands/lsmmap.c b/grub-core/commands/lsmmap.c index 657f81387..44598f0df 100644 --- a/grub-core/commands/lsmmap.c +++ b/grub-core/commands/lsmmap.c @@ -22,6 +22,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const char *names[] = { [GRUB_MEMORY_AVAILABLE] = "available", diff --git a/grub-core/commands/lspci.c b/grub-core/commands/lspci.c index fd2d4eaf2..03541df6c 100644 --- a/grub-core/commands/lspci.c +++ b/grub-core/commands/lspci.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_pci_classname { int class; diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c index 28aac7d81..3b51189d6 100644 --- a/grub-core/commands/memrw.c +++ b/grub-core/commands/memrw.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_extcmd_t cmd_read_byte, cmd_read_word, cmd_read_dword; static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword; diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c index 5cf109fde..c7d1ec4f5 100644 --- a/grub-core/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -29,6 +29,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* cat FILE */ static grub_err_t grub_mini_cmd_cat (struct grub_command *cmd __attribute__ ((unused)), diff --git a/grub-core/commands/mips/yeeloong/lsspd.c b/grub-core/commands/mips/yeeloong/lsspd.c index 539cda34c..c1c5e2ef7 100644 --- a/grub-core/commands/mips/yeeloong/lsspd.c +++ b/grub-core/commands/mips/yeeloong/lsspd.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c index 31e768553..a54286161 100644 --- a/grub-core/commands/parttool.c +++ b/grub-core/commands/parttool.c @@ -31,6 +31,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv2+"); + static struct grub_parttool *parts = 0; static int curhandle = 0; static grub_dl_t mymod; diff --git a/grub-core/commands/password.c b/grub-core/commands/password.c index db5951cbb..8821607b8 100644 --- a/grub-core/commands/password.c +++ b/grub-core/commands/password.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; static grub_err_t diff --git a/grub-core/commands/password_pbkdf2.c b/grub-core/commands/password_pbkdf2.c index 6886987da..05a627219 100644 --- a/grub-core/commands/password_pbkdf2.c +++ b/grub-core/commands/password_pbkdf2.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; struct pbkdf2_password diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c index 780d075ab..7ed2a4e51 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -32,9 +32,11 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { - {"set", 's', GRUB_ARG_OPTION_OPTIONAL, + {"set", 's', 0, N_("Set a variable to return value."), "VAR", ARG_TYPE_STRING}, {"driver", 'd', 0, N_("Determine driver."), 0, 0}, {"partmap", 'p', 0, N_("Determine partition map type."), 0, 0}, @@ -150,7 +152,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (probe) { - cmd = grub_register_extcmd ("probe", grub_cmd_probe, 0, N_("[DEVICE]"), + cmd = grub_register_extcmd ("probe", grub_cmd_probe, 0, N_("DEVICE"), N_("Retrieve device info."), options); } diff --git a/grub-core/commands/read.c b/grub-core/commands/read.c index 6a187fc3e..fe3e88b15 100644 --- a/grub-core/commands/read.c +++ b/grub-core/commands/read.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static char * grub_getline (void) { diff --git a/grub-core/commands/reboot.c b/grub-core/commands/reboot.c index eedd53c91..8e18083c0 100644 --- a/grub-core/commands/reboot.c +++ b/grub-core/commands/reboot.c @@ -22,6 +22,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c index 83c0d8d43..1e8a6f309 100644 --- a/grub-core/commands/regexp.c +++ b/grub-core/commands/regexp.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { { "set", 's', GRUB_ARG_OPTION_REPEATABLE, diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c index f265f86d6..ba80d80ef 100644 --- a/grub-core/commands/search.c +++ b/grub-core/commands/search.c @@ -31,6 +31,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + void FUNC_NAME (const char *key, const char *var, int no_floppy, char **hints, unsigned nhints) diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c index 80741d7ab..7b0a99565 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"file", 'f', 0, N_("Search devices by a file."), 0, 0}, diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c index 88dfa4c08..70f5bcdad 100644 --- a/grub-core/commands/setpci.c +++ b/grub-core/commands/setpci.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct pci_register { const char *name; diff --git a/grub-core/commands/sleep.c b/grub-core/commands/sleep.c index da642fcd9..97e7a40a6 100644 --- a/grub-core/commands/sleep.c +++ b/grub-core/commands/sleep.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const struct grub_arg_option options[] = { {"verbose", 'v', 0, N_("Verbose countdown."), 0, 0}, diff --git a/grub-core/commands/terminal.c b/grub-core/commands/terminal.c index c2d9550f6..0adfd3d2e 100644 --- a/grub-core/commands/terminal.c +++ b/grub-core/commands/terminal.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_term_autoload *grub_term_input_autoload = NULL; struct grub_term_autoload *grub_term_output_autoload = NULL; diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c index e981c945a..50d5aba5e 100644 --- a/grub-core/commands/test.c +++ b/grub-core/commands/test.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* A simple implementation for signed numbers. */ static int grub_strtosl (char *arg, char **end, int base) diff --git a/grub-core/commands/testload.c b/grub-core/commands/testload.c index 86b8a9253..fe06f3d1e 100644 --- a/grub-core/commands/testload.c +++ b/grub-core/commands/testload.c @@ -29,6 +29,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) diff --git a/grub-core/commands/true.c b/grub-core/commands/true.c index aa8125853..82775e7ef 100644 --- a/grub-core/commands/true.c +++ b/grub-core/commands/true.c @@ -21,6 +21,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_true (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/grub-core/commands/usbtest.c b/grub-core/commands/usbtest.c index 7f00c8856..4a051ad1f 100644 --- a/grub-core/commands/usbtest.c +++ b/grub-core/commands/usbtest.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static const char *usb_classes[] = { "Unknown", diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 10f77915b..3e0c1a12e 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static unsigned height, width, depth; static int diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c index 435ac2937..dc7a6485f 100644 --- a/grub-core/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) diff --git a/grub-core/commands/xnu_uuid.c b/grub-core/commands/xnu_uuid.c index 382d3196b..f618b4ec0 100644 --- a/grub-core/commands/xnu_uuid.c +++ b/grub-core/commands/xnu_uuid.c @@ -34,6 +34,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* This prefix is used by xnu and boot-132 to hash together with volume serial. */ static grub_uint8_t hash_prefix[16] diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index fe677e2a0..7f261560d 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* At the moment, only two IDE ports are supported. */ static const grub_port_t grub_ata_ioaddress[] = { GRUB_ATA_CH0_PORT1, GRUB_ATA_CH1_PORT1 }; diff --git a/grub-core/disk/ata_pthru.c b/grub-core/disk/ata_pthru.c index f52725a49..eb9cb5f85 100644 --- a/grub-core/disk/ata_pthru.c +++ b/grub-core/disk/ata_pthru.c @@ -22,6 +22,7 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); /* ATA pass through support, used by hdparm.mod. */ static grub_err_t diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c index d3f45935c..154193eb0 100644 --- a/grub-core/disk/dmraid_nvidia.c +++ b/grub-core/disk/dmraid_nvidia.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define NV_SIGNATURES 4 #define NV_IDLE 0 diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 069bb0b59..1d47dc727 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static int cd_drive = 0; static int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap); diff --git a/grub-core/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c index a2c717cdb..e9450167e 100644 --- a/grub-core/disk/ieee1275/nand.c +++ b/grub-core/disk/ieee1275/nand.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_nand_data { grub_ieee1275_ihandle_t handle; diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index b05940a4a..d50f353b1 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_loopback { char *devname; @@ -97,10 +99,6 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) if (newdev) { - char *newname = grub_strdup (args[1]); - if (! newname) - goto fail; - grub_file_close (newdev->file); newdev->file = file; @@ -166,7 +164,7 @@ grub_loopback_open (const char *name, grub_disk_t disk) disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; disk->id = (unsigned long) dev; - disk->data = dev->file; + disk->data = dev; return 0; } @@ -175,7 +173,7 @@ static grub_err_t grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) { - grub_file_t file = (grub_file_t) disk->data; + grub_file_t file = ((struct grub_loopback *) disk->data)->file; grub_off_t pos; grub_file_seek (file, sector << GRUB_DISK_SECTOR_BITS); diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 5a79063da..206e3e220 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -28,6 +28,8 @@ #include #endif +GRUB_MOD_LICENSE ("GPLv3+"); + static struct grub_lvm_vg *vg_list; static int lv_count; @@ -165,6 +167,31 @@ grub_lvm_close (grub_disk_t disk __attribute ((unused))) return; } +static grub_err_t +read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, + grub_size_t size, char *buf); + +static grub_err_t +read_node (const struct grub_lvm_node *node, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + /* Check whether we actually know the physical volume we want to + read from. */ + if (node->pv) + { + if (node->pv->disk) + return grub_disk_read (node->pv->disk, sector + node->pv->start, 0, + size << GRUB_DISK_SECTOR_BITS, buf); + else + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "physical volume %s not found", node->pv->name); + + } + if (node->lv) + return read_lv (node->lv, sector, size, buf); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name); +} + static grub_err_t read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, grub_size_t size, char *buf) @@ -172,7 +199,7 @@ read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, grub_err_t err = 0; struct grub_lvm_vg *vg = lv->vg; struct grub_lvm_segment *seg = lv->segments; - struct grub_lvm_pv *pv; + struct grub_lvm_node *node; grub_uint64_t offset; grub_uint64_t extent; unsigned int i; @@ -200,17 +227,17 @@ read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, switch (seg->type) { case GRUB_LVM_STRIPED: - if (seg->stripe_count == 1) + if (seg->node_count == 1) { /* This segment is linear, so that's easy. We just need to find out the offset in the physical volume and read SIZE bytes from that. */ - struct grub_lvm_stripe *stripe = seg->stripes; + struct grub_lvm_node *stripe = seg->nodes; grub_uint64_t seg_offset; /* Offset of the segment in PV device. */ - pv = stripe->pv; + node = stripe; seg_offset = ((grub_uint64_t) stripe->start - * (grub_uint64_t) vg->extent_size) + pv->start; + * (grub_uint64_t) vg->extent_size); offset = sector - ((grub_uint64_t) seg->start_extent * (grub_uint64_t) vg->extent_size) + seg_offset; @@ -219,7 +246,7 @@ read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, { /* This is a striped segment. We have to find the right PV similar to RAID0. */ - struct grub_lvm_stripe *stripe = seg->stripes; + struct grub_lvm_node *stripe = seg->nodes; grub_uint32_t a, b; grub_uint64_t seg_offset; /* Offset of the segment in PV device. */ unsigned int stripenr; @@ -228,42 +255,29 @@ read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, * (grub_uint64_t) vg->extent_size); a = grub_divmod64 (offset, seg->stripe_size, NULL); - grub_divmod64 (a, seg->stripe_count, &stripenr); + grub_divmod64 (a, seg->node_count, &stripenr); - a = grub_divmod64 (offset, seg->stripe_size * seg->stripe_count, NULL); + a = grub_divmod64 (offset, seg->stripe_size * seg->node_count, NULL); grub_divmod64 (offset, seg->stripe_size, &b); offset = a * seg->stripe_size + b; stripe += stripenr; - pv = stripe->pv; + node = stripe; seg_offset = ((grub_uint64_t) stripe->start - * (grub_uint64_t) vg->extent_size) + pv->start; + * (grub_uint64_t) vg->extent_size); offset += seg_offset; } - /* Check whether we actually know the physical volume we want to - read from. */ - if (pv->disk) - err = grub_disk_read (pv->disk, offset, 0, - size << GRUB_DISK_SECTOR_BITS, buf); - else - err = grub_error (GRUB_ERR_UNKNOWN_DEVICE, - "physical volume %s not found", pv->name); - - return err; + return read_node (node, offset, size, buf); case GRUB_LVM_MIRROR: i = 0; while (1) { - if (!seg->mirrors[i].lv) - err = grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume '%s'", - seg->mirrors[i].lvname); - else - err = read_lv (seg->mirrors[i].lv, sector, size, buf); + err = read_node (&seg->nodes[i], sector, size, buf); if (!err) return err; - if (++i >= seg->mirror_count) + if (++i >= seg->node_count) return err; grub_errno = GRUB_ERR_NONE; } @@ -544,6 +558,7 @@ grub_lvm_scan_device (const char *name) int skip_lv = 0; struct grub_lvm_lv *lv; struct grub_lvm_segment *seg; + int is_pvmove; while (grub_isspace (*p)) p++; @@ -567,6 +582,7 @@ grub_lvm_scan_device (const char *name) lv->size = 0; lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE"); + is_pvmove = grub_lvm_check_flag (p, "status", "PVMOVE"); lv->segment_count = grub_lvm_getvalue (&p, "segment_count = "); if (p == NULL) @@ -618,10 +634,10 @@ grub_lvm_scan_device (const char *name) if (grub_memcmp (p, "striped\"", sizeof ("striped\"") - 1) == 0) { - struct grub_lvm_stripe *stripe; + struct grub_lvm_node *stripe; seg->type = GRUB_LVM_STRIPED; - seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = "); + seg->node_count = grub_lvm_getvalue (&p, "stripe_count = "); if (p == NULL) { #ifdef GRUB_UTIL @@ -630,12 +646,12 @@ grub_lvm_scan_device (const char *name) goto lvs_segment_fail; } - if (seg->stripe_count != 1) + if (seg->node_count != 1) seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); - seg->stripes = grub_malloc (sizeof (*stripe) - * seg->stripe_count); - stripe = seg->stripes; + seg->nodes = grub_zalloc (sizeof (*stripe) + * seg->node_count); + stripe = seg->nodes; p = grub_strstr (p, "stripes = ["); if (p == NULL) @@ -647,10 +663,8 @@ grub_lvm_scan_device (const char *name) } p += sizeof("stripes = [") - 1; - for (j = 0; j < seg->stripe_count; j++) + for (j = 0; j < seg->node_count; j++) { - char *pvname; - p = grub_strchr (p, '"'); if (p == NULL) continue; @@ -660,24 +674,12 @@ grub_lvm_scan_device (const char *name) s = q - p; - pvname = grub_malloc (s + 1); - if (pvname == NULL) + stripe->name = grub_malloc (s + 1); + if (stripe->name == NULL) goto lvs_segment_fail2; - grub_memcpy (pvname, p, s); - pvname[s] = '\0'; - - if (vg->pvs) - for (pv = vg->pvs; pv; pv = pv->next) - { - if (! grub_strcmp (pvname, pv->name)) - { - stripe->pv = pv; - break; - } - } - - grub_free(pvname); + grub_memcpy (stripe->name, p, s); + stripe->name[s] = '\0'; stripe->start = grub_lvm_getvalue (&p, ","); if (p == NULL) @@ -690,7 +692,7 @@ grub_lvm_scan_device (const char *name) == 0) { seg->type = GRUB_LVM_MIRROR; - seg->mirror_count = grub_lvm_getvalue (&p, "mirror_count = "); + seg->node_count = grub_lvm_getvalue (&p, "mirror_count = "); if (p == NULL) { #ifdef GRUB_UTIL @@ -699,8 +701,8 @@ grub_lvm_scan_device (const char *name) goto lvs_segment_fail; } - seg->mirrors = grub_zalloc (sizeof (seg->mirrors[0]) - * seg->mirror_count); + seg->nodes = grub_zalloc (sizeof (seg->nodes[0]) + * seg->node_count); p = grub_strstr (p, "mirrors = ["); if (p == NULL) @@ -712,7 +714,7 @@ grub_lvm_scan_device (const char *name) } p += sizeof("mirrors = [") - 1; - for (j = 0; j < seg->mirror_count; j++) + for (j = 0; j < seg->node_count; j++) { char *lvname; @@ -731,9 +733,12 @@ grub_lvm_scan_device (const char *name) grub_memcpy (lvname, p, s); lvname[s] = '\0'; - seg->mirrors[j].lvname = lvname; + seg->nodes[j].name = lvname; p = q + 1; } + /* Only first (original) is ok with in progress pvmove. */ + if (is_pvmove) + seg->node_count = 1; } else { @@ -755,7 +760,7 @@ grub_lvm_scan_device (const char *name) continue; lvs_segment_fail2: - grub_free (seg->stripes); + grub_free (seg->nodes); lvs_segment_fail: goto fail4; } @@ -786,18 +791,31 @@ grub_lvm_scan_device (const char *name) } } - /* Match mirrors */ + /* Match lvs. */ { struct grub_lvm_lv *lv1; struct grub_lvm_lv *lv2; for (lv1 = vg->lvs; lv1; lv1 = lv1->next) for (i = 0; i < lv1->segment_count; i++) - if (lv1->segments[i].type == GRUB_LVM_MIRROR) - for (j = 0; j < lv1->segments[i].mirror_count; j++) - for (lv2 = vg->lvs; lv2; lv2 = lv2->next) - if (grub_strcmp (lv2->name + grub_strlen (vg->name) + 1, - lv1->segments[i].mirrors[j].lvname) == 0) - lv1->segments[i].mirrors[j].lv = lv2; + for (j = 0; j < lv1->segments[i].node_count; j++) + { + if (vg->pvs) + for (pv = vg->pvs; pv; pv = pv->next) + { + if (! grub_strcmp (pv->name, + lv1->segments[i].nodes[j].name)) + { + lv1->segments[i].nodes[j].pv = pv; + break; + } + } + if (lv1->segments[i].nodes[j].pv == NULL) + for (lv2 = vg->lvs; lv2; lv2 = lv2->next) + if (grub_strcmp (lv2->name + grub_strlen (vg->name) + 1, + lv1->segments[i].nodes[j].name) == 0) + lv1->segments[i].nodes[j].lv = lv2; + } + } vg->next = vg_list; @@ -838,6 +856,7 @@ grub_lvm_scan_device (const char *name) grub_disk_close (disk); if (grub_errno == GRUB_ERR_OUT_OF_RANGE) grub_errno = GRUB_ERR_NONE; + grub_print_error (); return 0; } diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c index 1d08abf5b..19c43f455 100644 --- a/grub-core/disk/mdraid1x_linux.c +++ b/grub-core/disk/mdraid1x_linux.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* Linux RAID on disk structures and constants, copied from include/linux/raid/md_p.h. */ @@ -200,11 +202,14 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, if (grub_le_to_cpu32 (real_sb->dev_number) >= grub_le_to_cpu32 (real_sb->max_dev)) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + return grub_error (GRUB_ERR_OUT_OF_RANGE, "spares aren't implemented"); array->index = grub_le_to_cpu16 (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]); + if (array->index >= array->total_devs) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "spares aren't implemented"); array->uuid_len = 16; array->uuid = grub_malloc (16); if (!array->uuid) diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c index 7aa48fd7a..0e2d85009 100644 --- a/grub-core/disk/mdraid_linux.c +++ b/grub-core/disk/mdraid_linux.c @@ -27,6 +27,8 @@ /* Linux RAID on disk structures and constants, copied from include/linux/raid/md_p.h. */ +GRUB_MOD_LICENSE ("GPLv3+"); + #define RESERVED_BYTES (64 * 1024) #define RESERVED_SECTORS (RESERVED_BYTES / 512) @@ -202,7 +204,7 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, "unsupported RAID level: %d", level); if (grub_le_to_cpu32 (sb.this_disk.number) == 0xffff || grub_le_to_cpu32 (sb.this_disk.number) == 0xfffe) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + return grub_error (GRUB_ERR_OUT_OF_RANGE, "spares aren't implemented"); array->name = NULL; @@ -219,10 +221,10 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, return grub_errno; uuid = (grub_uint32_t *) array->uuid; - uuid[0] = sb.set_uuid0; - uuid[1] = sb.set_uuid1; - uuid[2] = sb.set_uuid2; - uuid[3] = sb.set_uuid3; + uuid[0] = grub_swap_bytes32 (sb.set_uuid0); + uuid[1] = grub_swap_bytes32 (sb.set_uuid1); + uuid[2] = grub_swap_bytes32 (sb.set_uuid2); + uuid[3] = grub_swap_bytes32 (sb.set_uuid3); *start_sector = 0; diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index e00280dd7..114ac0d9e 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static char *memdisk_addr; static grub_off_t memdisk_size = 0; diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index c89ca62a1..946e6d2c2 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -23,6 +23,11 @@ #include #include #include +#ifdef GRUB_UTIL +#include +#endif + +GRUB_MOD_LICENSE ("GPLv3+"); /* Linked list of RAID arrays. */ static struct grub_raid_array *array_list; @@ -117,18 +122,49 @@ grub_raid_getname (struct grub_disk *disk) } #endif +static inline int +ascii2hex (char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return 0; +} + static grub_err_t grub_raid_open (const char *name, grub_disk_t disk) { struct grub_raid_array *array; unsigned n; - for (array = array_list; array != NULL; array = array->next) + if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0) { - if (!grub_strcmp (array->name, name)) - if (grub_is_array_readable (array)) - break; + const char *uuidstr = name + sizeof ("mduuid/") - 1; + grub_size_t uuid_len = grub_strlen (uuidstr) / 2; + grub_uint8_t uuidbin[uuid_len]; + unsigned i; + for (i = 0; i < uuid_len; i++) + uuidbin[i] = ascii2hex (uuidstr[2 * i + 1]) + | (ascii2hex (uuidstr[2 * i]) << 4); + + for (array = array_list; array != NULL; array = array->next) + { + if (uuid_len == (unsigned) array->uuid_len + && grub_memcmp (uuidbin, array->uuid, uuid_len) == 0) + if (grub_is_array_readable (array)) + break; + } } + else + for (array = array_list; array != NULL; array = array->next) + { + if (!grub_strcmp (array->name, name)) + if (grub_is_array_readable (array)) + break; + } if (!array) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s", diff --git a/grub-core/disk/raid5_recover.c b/grub-core/disk/raid5_recover.c index 349eb0291..c26d05e94 100644 --- a/grub-core/disk/raid5_recover.c +++ b/grub-core/disk/raid5_recover.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_raid5_recover (struct grub_raid_array *array, int disknr, char *buf, grub_disk_addr_t sector, int size) diff --git a/grub-core/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c index dfaa60ea4..25b50eb6b 100644 --- a/grub-core/disk/raid6_recover.c +++ b/grub-core/disk/raid6_recover.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_uint8_t raid6_table1[256][256]; static grub_uint8_t raid6_table2[256][256]; diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index a40de278f..25f0e3aea 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_scsi_dev_t grub_scsi_dev_list; diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c index fcfe9e5d4..2f1dbd487 100644 --- a/grub-core/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_USBMS_DIRECTION_BIT 7 /* The USB Mass Storage Command Block Wrapper. */ diff --git a/grub-core/efiemu/main.c b/grub-core/efiemu/main.c index da813b00d..7ad3abb0d 100644 --- a/grub-core/efiemu/main.c +++ b/grub-core/efiemu/main.c @@ -32,6 +32,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* System table. Two version depending on mode */ grub_efi_system_table32_t *grub_efiemu_system_table32 = 0; grub_efi_system_table64_t *grub_efiemu_system_table64 = 0; @@ -191,7 +193,7 @@ grub_efiemu_load_file (const char *filename) file = grub_file_open (filename); if (! file) - return 0; + return grub_errno; err = grub_efiemu_mm_init (); if (err) diff --git a/grub-core/font/font.c b/grub-core/font/font.c index b5ec43bb2..ef6caf77b 100644 --- a/grub-core/font/font.c +++ b/grub-core/font/font.c @@ -30,6 +30,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #ifdef USE_ASCII_FAILBACK #include "ascii.h" #endif diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 40be4b2f6..1c4f80ec0 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* The affs bootblock. */ struct grub_affs_bblock { diff --git a/grub-core/fs/afs.c b/grub-core/fs/afs.c index cd61f4db9..35ef49937 100644 --- a/grub-core/fs/afs.c +++ b/grub-core/fs/afs.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #ifdef MODE_BIGENDIAN #define GRUB_AFS_FSNAME_SUFFIX "_be" #else diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 179891da8..42aa257d9 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -24,72 +24,1404 @@ #include #include #include +#include +#include -#define BTRFS_SIGNATURE "_BHRfS_M" +GRUB_MOD_LICENSE ("GPLv3+"); -struct btrfs_superblock -{ - grub_uint8_t dummy1[32]; - grub_uint16_t uuid[8]; - grub_uint8_t dummy2[16]; - grub_uint8_t signature[sizeof (BTRFS_SIGNATURE) - 1]; +#define GRUB_BTRFS_SIGNATURE "_BHRfS_M" + +typedef grub_uint8_t grub_btrfs_checksum_t[0x20]; +typedef grub_uint16_t grub_btrfs_uuid_t[8]; + +struct grub_btrfs_device +{ + grub_uint64_t device_id; + grub_uint8_t dummy[0x62 - 8]; } __attribute__ ((packed)); +struct grub_btrfs_superblock +{ + grub_btrfs_checksum_t checksum; + grub_btrfs_uuid_t uuid; + grub_uint8_t dummy[0x10]; + grub_uint8_t signature[sizeof (GRUB_BTRFS_SIGNATURE) - 1]; + grub_uint64_t generation; + grub_uint64_t root_tree; + grub_uint64_t chunk_tree; + grub_uint8_t dummy2[0x20]; + grub_uint64_t root_dir_objectid; + grub_uint8_t dummy3[0x41]; + struct grub_btrfs_device this_device; + char label[0x100]; + grub_uint8_t dummy4[0x100]; + grub_uint8_t bootstrap_mapping[0x800]; +} __attribute__ ((packed)); + +struct btrfs_header +{ + grub_btrfs_checksum_t checksum; + grub_btrfs_uuid_t uuid; + grub_uint8_t dummy[0x30]; + grub_uint32_t nitems; + grub_uint8_t level; +} __attribute__ ((packed)); + +struct grub_btrfs_device_desc +{ + grub_device_t dev; + grub_uint64_t id; +}; + struct grub_btrfs_data { - struct btrfs_superblock sblock; + struct grub_btrfs_superblock sblock; + grub_uint64_t tree; + grub_uint64_t inode; + + struct grub_btrfs_device_desc *devices_attached; + unsigned n_devices_attached; + unsigned n_devices_allocated; + + /* Cached extent data. */ + grub_uint64_t extstart; + grub_uint64_t extend; + grub_uint64_t extino; + grub_uint64_t exttree; + grub_size_t extsize; + struct grub_btrfs_extent_data *extent; }; -static struct grub_btrfs_data * -grub_btrfs_mount (grub_disk_t disk) +struct grub_btrfs_key { - struct grub_btrfs_data *data = grub_malloc (sizeof (*data)); + grub_uint64_t object_id; +#define GRUB_BTRFS_ITEM_TYPE_INODE_ITEM 0x01 +#define GRUB_BTRFS_ITEM_TYPE_DIR_ITEM 0x54 +#define GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM 0x6c +#define GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM 0x84 +#define GRUB_BTRFS_ITEM_TYPE_DEVICE 0xd8 +#define GRUB_BTRFS_ITEM_TYPE_CHUNK 0xe4 + grub_uint8_t type; + grub_uint64_t offset; +} __attribute__ ((packed)); + +struct grub_btrfs_chunk_item +{ + grub_uint64_t size; + grub_uint64_t dummy; + grub_uint64_t stripe_length; + grub_uint64_t type; +#define GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE 0x07 +#define GRUB_BTRFS_CHUNK_TYPE_SINGLE 0x00 +#define GRUB_BTRFS_CHUNK_TYPE_RAID0 0x08 +#define GRUB_BTRFS_CHUNK_TYPE_RAID1 0x10 +#define GRUB_BTRFS_CHUNK_TYPE_DUPLICATED 0x20 +#define GRUB_BTRFS_CHUNK_TYPE_RAID10 0x40 + grub_uint8_t dummy2[0xc]; + grub_uint16_t nstripes; + grub_uint16_t nsubstripes; +} __attribute__ ((packed)); + +struct grub_btrfs_chunk_stripe +{ + grub_uint64_t device_id; + grub_uint64_t offset; + grub_btrfs_uuid_t device_uuid; +} __attribute__ ((packed)); + +struct grub_btrfs_leaf_node +{ + struct grub_btrfs_key key; + grub_uint32_t offset; + grub_uint32_t size; +} __attribute__ ((packed)); + +struct grub_btrfs_internal_node +{ + struct grub_btrfs_key key; + grub_uint64_t addr; + grub_uint64_t dummy; +} __attribute__ ((packed)); + +struct grub_btrfs_dir_item +{ + struct grub_btrfs_key key; + grub_uint8_t dummy[8]; + grub_uint16_t m; + grub_uint16_t n; +#define GRUB_BTRFS_DIR_ITEM_TYPE_REGULAR 1 +#define GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY 2 +#define GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK 7 + grub_uint8_t type; + char name[0]; +} __attribute__ ((packed)); + +struct grub_btrfs_leaf_descriptor +{ + unsigned depth; + unsigned allocated; + struct { + grub_disk_addr_t addr; + unsigned iter; + unsigned maxiter; + int leaf; + } *data; +}; + +struct grub_btrfs_root_item +{ + grub_uint8_t dummy[0xb0]; + grub_uint64_t tree; + grub_uint64_t inode; +}; + +struct grub_btrfs_time +{ + grub_int64_t sec; + grub_uint32_t nanosec; +} __attribute__ ((aligned(4))); + +struct grub_btrfs_inode +{ + grub_uint8_t dummy1[0x10]; + grub_uint64_t size; + grub_uint8_t dummy2[0x70]; + struct grub_btrfs_time mtime; +} __attribute__ ((packed)); + +struct grub_btrfs_extent_data +{ + grub_uint64_t dummy; + grub_uint64_t size; + grub_uint8_t compression; + grub_uint8_t encryption; + grub_uint16_t encoding; + grub_uint8_t type; + union + { + char inl[0]; + struct + { + grub_uint64_t laddr; + grub_uint64_t compressed_size; + grub_uint64_t offset; + grub_uint64_t filled; + }; + }; +} __attribute__ ((packed)); + +#define GRUB_BTRFS_EXTENT_INLINE 0 +#define GRUB_BTRFS_EXTENT_REGULAR 1 + +#define GRUB_BTRFS_COMPRESSION_NONE 0 +#define GRUB_BTRFS_COMPRESSION_ZLIB 1 + +#define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100 + +static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2, + 256 * 1048576 * 2, + 1048576ULL * 1048576ULL * 2 }; + +static grub_err_t +grub_btrfs_read_logical (struct grub_btrfs_data *data, + grub_disk_addr_t addr, void *buf, grub_size_t size); + +static grub_err_t +read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb) +{ + unsigned i; + grub_err_t err = GRUB_ERR_NONE; + for (i = 0; i < ARRAY_SIZE (superblock_sectors); i++) + { + struct grub_btrfs_superblock sblock; + err = grub_disk_read (disk, superblock_sectors[i], 0, + sizeof (sblock), &sblock); + if (err == GRUB_ERR_OUT_OF_RANGE) + break; + + if (grub_memcmp ((char *) sblock.signature, GRUB_BTRFS_SIGNATURE, + sizeof (GRUB_BTRFS_SIGNATURE) - 1) != 0) + break; + if (i == 0 || grub_le_to_cpu64 (sblock.generation) + > grub_le_to_cpu64 (sb->generation)) + grub_memcpy (sb, &sblock, sizeof (sblock)); + } + + if ((err == GRUB_ERR_OUT_OF_RANGE || !err) && i == 0) + return grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem"); + + if (err == GRUB_ERR_OUT_OF_RANGE) + grub_errno = err = GRUB_ERR_NONE; + + return err; +} + +static int +key_cmp (const struct grub_btrfs_key *a, const struct grub_btrfs_key *b) +{ + if (grub_cpu_to_le64 (a->object_id) < grub_cpu_to_le64 (b->object_id)) + return -1; + if (grub_cpu_to_le64 (a->object_id) > grub_cpu_to_le64 (b->object_id)) + return +1; + + if (a->type < b->type) + return -1; + if (a->type > b->type) + return +1; + + if (grub_cpu_to_le64 (a->offset) < grub_cpu_to_le64 (b->offset)) + return -1; + if (grub_cpu_to_le64 (a->offset) > grub_cpu_to_le64 (b->offset)) + return +1; + return 0; +} + +static void +free_iterator (struct grub_btrfs_leaf_descriptor *desc) +{ + grub_free (desc->data); +} + +static grub_err_t +save_ref (struct grub_btrfs_leaf_descriptor *desc, + grub_disk_addr_t addr, unsigned i, unsigned m, int l) +{ + desc->depth++; + if (desc->allocated < desc->depth) + { + void *newdata; + desc->allocated *= 2; + newdata = grub_realloc (desc->data, sizeof (desc->data[0]) + * desc->allocated); + if (!newdata) + return grub_errno; + desc->data = newdata; + } + desc->data[desc->depth - 1].addr = addr; + desc->data[desc->depth - 1].iter = i; + desc->data[desc->depth - 1].maxiter = m; + desc->data[desc->depth - 1].leaf = l; + return GRUB_ERR_NONE; +} + +static int +next (struct grub_btrfs_data *data, + struct grub_btrfs_leaf_descriptor *desc, + grub_disk_addr_t *outaddr, grub_size_t *outsize, + struct grub_btrfs_key *key_out) +{ + grub_err_t err; + struct grub_btrfs_leaf_node leaf; + + for (; desc->depth > 0; desc->depth--) + { + desc->data[desc->depth - 1].iter++; + if (desc->data[desc->depth - 1].iter + < desc->data[desc->depth - 1].maxiter) + break; + } + if (desc->depth == 0) + return 0; + while (!desc->data[desc->depth - 1].leaf) + { + struct grub_btrfs_internal_node node; + struct btrfs_header head; + + err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter + * sizeof (node) + + sizeof (struct btrfs_header) + + desc->data[desc->depth - 1].addr, &node, + sizeof (node)); + if (err) + return -err; + + err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr), &head, + sizeof (head)); + if (err) + return -err; + + save_ref (desc, grub_le_to_cpu64 (node.addr), 0, + grub_le_to_cpu32 (head.nitems), !head.level); + } + err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter + * sizeof (leaf) + + sizeof (struct btrfs_header) + + desc->data[desc->depth - 1].addr, &leaf, + sizeof (leaf)); + if (err) + return -err; + *outsize = grub_le_to_cpu32 (leaf.size); + *outaddr = desc->data[desc->depth - 1].addr + sizeof (struct btrfs_header) + + grub_le_to_cpu32 (leaf.offset); + *key_out = leaf.key; + return 1; +} + +static grub_err_t +lower_bound (struct grub_btrfs_data *data, + const struct grub_btrfs_key *key_in, + struct grub_btrfs_key *key_out, + grub_disk_addr_t root, + grub_disk_addr_t *outaddr, grub_size_t *outsize, + struct grub_btrfs_leaf_descriptor *desc) +{ + grub_disk_addr_t addr = root; + int depth = -1; + + if (desc) + { + desc->allocated = 16; + desc->depth = 0; + desc->data = grub_malloc (sizeof (desc->data[0]) * desc->allocated); + if (!desc->data) + return grub_errno; + } + + grub_dprintf ("btrfs", + "retrieving %" PRIxGRUB_UINT64_T + " %x %" PRIxGRUB_UINT64_T "\n", + key_in->object_id, key_in->type, key_in->offset); + + while (1) + { + grub_err_t err; + struct btrfs_header head; + + reiter: + depth++; + /* FIXME: preread few nodes into buffer. */ + err = grub_btrfs_read_logical (data, addr, &head, sizeof (head)); + if (err) + return err; + addr += sizeof (head); + if (head.level) + { + unsigned i; + struct grub_btrfs_internal_node node, node_last; + int have_last = 0; + grub_memset (&node_last, 0, sizeof (node_last)); + for (i = 0; i < grub_le_to_cpu32 (head.nitems); i++) + { + err = grub_btrfs_read_logical (data, addr + i * sizeof (node), + &node, sizeof (node)); + if (err) + return err; + + grub_dprintf ("btrfs", + "internal node (depth %d) %" PRIxGRUB_UINT64_T + " %x %" PRIxGRUB_UINT64_T "\n", depth, + node.key.object_id, node.key.type, node.key.offset); + + if (key_cmp (&node.key, key_in) == 0) + { + err = GRUB_ERR_NONE; + if (desc) + err = save_ref (desc, addr - sizeof (head), i, + grub_le_to_cpu32 (head.nitems), 0); + if (err) + return err; + addr = grub_le_to_cpu64 (node.addr); + goto reiter; + } + if (key_cmp (&node.key, key_in) > 0) + break; + node_last = node; + have_last = 1; + } + if (have_last) + { + err = GRUB_ERR_NONE; + if (desc) + err = save_ref (desc, addr - sizeof (head), i - 1, + grub_le_to_cpu32 (head.nitems), 0); + if (err) + return err; + addr = grub_le_to_cpu64 (node_last.addr); + goto reiter; + } + *outsize = 0; + *outaddr = 0; + grub_memset (key_out, 0, sizeof (*key_out)); + if (desc) + return save_ref (desc, addr - sizeof (head), -1, + grub_le_to_cpu32 (head.nitems), 0); + return GRUB_ERR_NONE; + } + { + unsigned i; + struct grub_btrfs_leaf_node leaf, leaf_last; + int have_last = 0; + for (i = 0; i < grub_le_to_cpu32 (head.nitems); i++) + { + err = grub_btrfs_read_logical (data, addr + i * sizeof (leaf), + &leaf, sizeof (leaf)); + if (err) + return err; + + grub_dprintf ("btrfs", + "leaf (depth %d) %" PRIxGRUB_UINT64_T + " %x %" PRIxGRUB_UINT64_T "\n", depth, + leaf.key.object_id, leaf.key.type, leaf.key.offset); + + if (key_cmp (&leaf.key, key_in) == 0) + { + grub_memcpy (key_out, &leaf.key, sizeof(*key_out)); + *outsize = grub_le_to_cpu32 (leaf.size); + *outaddr = addr + grub_le_to_cpu32 (leaf.offset); + if (desc) + return save_ref (desc, addr - sizeof (head), i, + grub_le_to_cpu32 (head.nitems), 1); + return GRUB_ERR_NONE; + } + + if (key_cmp (&leaf.key, key_in) > 0) + break; + + have_last = 1; + leaf_last = leaf; + } + + if (have_last) + { + grub_memcpy (key_out, &leaf_last.key, sizeof(*key_out)); + *outsize = grub_le_to_cpu32 (leaf_last.size); + *outaddr = addr + grub_le_to_cpu32 (leaf_last.offset); + if (desc) + return save_ref (desc, addr - sizeof (head), i - 1, + grub_le_to_cpu32 (head.nitems), 1); + return GRUB_ERR_NONE; + } + *outsize = 0; + *outaddr = 0; + grub_memset (key_out, 0, sizeof (*key_out)); + if (desc) + return save_ref (desc, addr - sizeof (head), -1, + grub_le_to_cpu32 (head.nitems), 1); + return GRUB_ERR_NONE; + } + } +} + +static grub_device_t +find_device (struct grub_btrfs_data *data, grub_uint64_t id, + int do_rescan) +{ + grub_device_t dev_found = NULL; + auto int hook (const char *name); + int hook (const char *name) + { + grub_device_t dev; + grub_err_t err; + struct grub_btrfs_superblock sb; + dev = grub_device_open (name); + if (!dev) + return 0; + if (!dev->disk) + { + grub_device_close (dev); + return 0; + } + err = read_sblock (dev->disk, &sb); + if (err == GRUB_ERR_BAD_FS) + { + grub_device_close (dev); + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (err) + { + grub_device_close (dev); + grub_print_error (); + return 0; + } + if (grub_memcmp (data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0 + || sb.this_device.device_id != id) + { + grub_device_close (dev); + return 0; + } + + dev_found = dev; + return 1; + } + + unsigned i; + + for (i = 0; i < data->n_devices_attached; i++) + if (id == data->devices_attached[i].id) + return data->devices_attached[i].dev; + if (do_rescan) + grub_device_iterate (hook); + if (!dev_found) + { + grub_error (GRUB_ERR_BAD_FS, "couldn't find a member device"); + return NULL; + } + data->n_devices_attached++; + if (data->n_devices_attached > data->n_devices_allocated) + { + void *tmp; + data->n_devices_allocated = 2 * data->n_devices_attached + 1; + data->devices_attached + = grub_realloc (tmp = data->devices_attached, + data->n_devices_allocated + * sizeof (data->devices_attached[0])); + if (!data->devices_attached) + { + grub_device_close (dev_found); + data->devices_attached = tmp; + return NULL; + } + } + data->devices_attached[data->n_devices_attached - 1].id = id; + data->devices_attached[data->n_devices_attached - 1].dev = dev_found; + return dev_found; +} + +static grub_err_t +grub_btrfs_read_logical (struct grub_btrfs_data *data, + grub_disk_addr_t addr, + void *buf, grub_size_t size) +{ + while (size > 0) + { + grub_uint8_t *ptr; + struct grub_btrfs_key *key; + struct grub_btrfs_chunk_item *chunk; + grub_uint64_t csize; + grub_err_t err; + struct grub_btrfs_key key_out; + int challoc = 0; + grub_device_t dev; + grub_dprintf ("btrfs", "searching for laddr %" PRIxGRUB_UINT64_T "\n", + addr); + for (ptr = data->sblock.bootstrap_mapping; + ptr < data->sblock.bootstrap_mapping + + sizeof (data->sblock.bootstrap_mapping) + - sizeof (struct grub_btrfs_key); + ) + { + key = (struct grub_btrfs_key *) ptr; + if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK) + break; + chunk = (struct grub_btrfs_chunk_item *) (key + 1); + grub_dprintf ("btrfs", "%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n", + grub_le_to_cpu64 (key->offset), + grub_le_to_cpu64 (chunk->size)); + if (grub_le_to_cpu64 (key->offset) <= addr + && addr < grub_le_to_cpu64 (key->offset) + + grub_le_to_cpu64 (chunk->size)) + goto chunk_found; + ptr += sizeof (*key) + sizeof (*chunk) + + sizeof (struct grub_btrfs_chunk_stripe) + * grub_le_to_cpu16 (chunk->nstripes); + } + struct grub_btrfs_key key_in; + grub_size_t chsize; + grub_disk_addr_t chaddr; + key_in.object_id = GRUB_BTRFS_OBJECT_ID_CHUNK; + key_in.type = GRUB_BTRFS_ITEM_TYPE_CHUNK; + key_in.offset = addr; + err = lower_bound (data, &key_in, &key_out, + grub_le_to_cpu64 (data->sblock.chunk_tree), + &chaddr, &chsize, NULL); + if (err) + return err; + key = &key_out; + if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK + || !(grub_le_to_cpu64 (key->offset) <= addr)) + return grub_error (GRUB_ERR_BAD_FS, + "couldn't find the chunk descriptor"); + + chunk = grub_malloc (chsize); + if (!chunk) + return grub_errno; + + challoc = 1; + err = grub_btrfs_read_logical (data, chaddr, chunk, chsize); + if (err) + { + grub_free (chunk); + return err; + } + + chunk_found: + { + grub_uint32_t stripen; + grub_uint64_t stripe_offset; + grub_uint64_t off = addr - grub_le_to_cpu64 (key->offset); + unsigned redundancy = 1; + unsigned i, j; + + if (grub_le_to_cpu64 (chunk->size) <= off) + { + grub_dprintf ("btrfs", "no chunk\n"); + return grub_error (GRUB_ERR_BAD_FS, + "couldn't find the chunk descriptor"); + } + + grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T + "+0x%" PRIxGRUB_UINT64_T + " (%d stripes (%d substripes) of %" + PRIxGRUB_UINT64_T ")\n", + grub_le_to_cpu64 (key->offset), + grub_le_to_cpu64 (chunk->size), + grub_le_to_cpu16 (chunk->nstripes), + grub_le_to_cpu16 (chunk->nsubstripes), + grub_le_to_cpu64 (chunk->stripe_length)); + + switch (grub_le_to_cpu64 (chunk->type) + & ~GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE) + { + case GRUB_BTRFS_CHUNK_TYPE_SINGLE: + { + grub_uint64_t stripe_length; + grub_dprintf ("btrfs", "single\n"); + stripe_length = grub_divmod64_full (grub_le_to_cpu64 (chunk->size), + grub_le_to_cpu16 (chunk->nstripes), + NULL); + stripen = grub_divmod64_full (off, stripe_length, &stripe_offset); + csize = (stripen + 1) * stripe_length - off; + break; + } + case GRUB_BTRFS_CHUNK_TYPE_DUPLICATED: + case GRUB_BTRFS_CHUNK_TYPE_RAID1: + { + grub_dprintf ("btrfs", "RAID1\n"); + stripen = 0; + stripe_offset = off; + csize = grub_le_to_cpu64 (chunk->size) - off; + redundancy = 2; + break; + } + case GRUB_BTRFS_CHUNK_TYPE_RAID0: + { + grub_uint64_t middle, high; + grub_uint32_t low; + grub_dprintf ("btrfs", "RAID0\n"); + middle = grub_divmod64 (off, + grub_le_to_cpu64 (chunk->stripe_length), + &low); + + high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes), + &stripen); + stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length) + * high; + csize = grub_le_to_cpu64 (chunk->stripe_length) - low; + break; + } + case GRUB_BTRFS_CHUNK_TYPE_RAID10: + { + grub_uint64_t middle, high; + grub_uint32_t low; + middle = grub_divmod64 (off, + grub_le_to_cpu64 (chunk->stripe_length), + &low); + + high = grub_divmod64 (middle, + grub_le_to_cpu16 (chunk->nsubstripes), + &stripen); + stripen *= grub_le_to_cpu16 (chunk->nstripes) + / grub_le_to_cpu16 (chunk->nsubstripes); + redundancy = grub_le_to_cpu16 (chunk->nstripes) + / grub_le_to_cpu16 (chunk->nsubstripes); + stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length) + * high; + csize = grub_le_to_cpu64 (chunk->stripe_length) - low; + break; + } + default: + grub_dprintf ("btrfs", "unsupported RAID\n"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported RAID flags %" PRIxGRUB_UINT64_T, + grub_le_to_cpu64 (chunk->type)); + } + if (csize == 0) + return grub_error (GRUB_ERR_BUG, + "couldn't find the chunk descriptor"); + if ((grub_size_t) csize > size) + csize = size; + + for (j = 0; j < 2; j++) + { + for (i = 0; i < redundancy; i++) + { + struct grub_btrfs_chunk_stripe *stripe; + grub_disk_addr_t paddr; + + stripe = (struct grub_btrfs_chunk_stripe *) (chunk + 1); + /* Right now the redundancy handling is easy. + With RAID5-like it will be more difficult. */ + stripe += stripen + i; + + paddr = stripe->offset + stripe_offset; + + grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T + "+0x%" PRIxGRUB_UINT64_T " (%d stripes (%d substripes) of %" + PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT32_T + " maps to 0x%" PRIxGRUB_UINT64_T "\n", + grub_le_to_cpu64 (key->offset), + grub_le_to_cpu64 (chunk->size), + grub_le_to_cpu16 (chunk->nstripes), + grub_le_to_cpu16 (chunk->nsubstripes), + grub_le_to_cpu64 (chunk->stripe_length), + stripen, stripe->offset); + grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T + " for laddr 0x%" PRIxGRUB_UINT64_T"\n", paddr, + addr); + + dev = find_device (data, stripe->device_id, j); + if (!dev) + { + err = grub_errno; + grub_errno = GRUB_ERR_NONE; + continue; + } + + err = grub_disk_read (dev->disk, paddr >> GRUB_DISK_SECTOR_BITS, + paddr & (GRUB_DISK_SECTOR_SIZE - 1), + csize, buf); + if (!err) + break; + grub_errno = GRUB_ERR_NONE; + } + if (i != redundancy) + break; + } + if (err) + return grub_errno = err; + } + size -= csize; + buf = (grub_uint8_t *) buf + csize; + addr += csize; + if (challoc) + grub_free (chunk); + } + return GRUB_ERR_NONE; +} + +static struct grub_btrfs_data * +grub_btrfs_mount (grub_device_t dev) +{ + struct grub_btrfs_data *data; + grub_err_t err; + + if (!dev->disk) + { + grub_error (GRUB_ERR_BAD_FS, "not BtrFS"); + return NULL; + } + + data = grub_zalloc (sizeof (*data)); if (! data) return NULL; - if (grub_disk_read (disk, 128, 0, sizeof (data->sblock), - &data->sblock) != GRUB_ERR_NONE) - goto fail; - - if (grub_memcmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1)) + err = read_sblock (dev->disk, &data->sblock); + if (err) { - grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem"); - goto fail; + grub_free (data); + return NULL; } + data->n_devices_allocated = 16; + data->devices_attached = grub_malloc (sizeof (data->devices_attached[0]) + * data->n_devices_allocated); + if (!data->devices_attached) + { + grub_free (data); + return NULL; + } + data->n_devices_attached = 1; + data->devices_attached[0].dev = dev; + data->devices_attached[0].id = data->sblock.this_device.device_id; + return data; +} - fail: - if (grub_errno == GRUB_ERR_OUT_OF_RANGE) - grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem"); - +static void +grub_btrfs_unmount (struct grub_btrfs_data *data) +{ + unsigned i; + /* The device 0 is closed one layer upper. */ + for (i = 1; i < data->n_devices_attached; i++) + grub_device_close (data->devices_attached[i].dev); + grub_free (data->devices_attached); + grub_free (data->extent); grub_free (data); - return NULL; } static grub_err_t -grub_btrfs_open (struct grub_file *file __attribute__ ((unused)), - const char *name __attribute__ ((unused))) +grub_btrfs_read_inode (struct grub_btrfs_data *data, + struct grub_btrfs_inode *inode, grub_uint64_t num, + grub_uint64_t tree) { - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "only detection is supported for Btrfs"); + struct grub_btrfs_key key_in, key_out; + grub_disk_addr_t elemaddr; + grub_size_t elemsize; + grub_err_t err; + + key_in.object_id = num; + key_in.type = GRUB_BTRFS_ITEM_TYPE_INODE_ITEM; + key_in.offset = 0; + + err = lower_bound (data, &key_in, &key_out, tree, + &elemaddr, &elemsize, NULL); + if (err) + return err; + if (num != key_out.object_id + || key_out.type != GRUB_BTRFS_ITEM_TYPE_INODE_ITEM) + return grub_error (GRUB_ERR_BAD_FS, "inode not found"); + + return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode)); +} + +static grub_ssize_t +grub_btrfs_extent_read (struct grub_btrfs_data *data, + grub_uint64_t ino, grub_uint64_t tree, + grub_off_t pos0, char *buf, grub_size_t len) +{ + grub_off_t pos = pos0; + while (len) + { + grub_size_t csize; + grub_err_t err; + grub_off_t extoff; + if (!data->extent || data->extstart > pos || data->extino != ino + || data->exttree != tree || data->extend <= pos) + { + struct grub_btrfs_key key_in, key_out; + grub_disk_addr_t elemaddr; + grub_size_t elemsize; + + grub_free (data->extent); + key_in.object_id = ino; + key_in.type = GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM; + key_in.offset = grub_cpu_to_le64 (pos); + err = lower_bound (data, &key_in, &key_out, tree, + &elemaddr, &elemsize, NULL); + if (err) + return -1; + if (key_out.object_id != ino + || key_out.type != GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM) + { + grub_error (GRUB_ERR_BAD_FS, "extent not found"); + return -1; + } + data->extstart = grub_le_to_cpu64 (key_out.offset); + data->extsize = elemsize; + data->extent = grub_malloc (elemsize); + data->extino = ino; + data->exttree = tree; + if (!data->extent) + return grub_errno; + + err = grub_btrfs_read_logical (data, elemaddr, + data->extent, elemsize); + if (err) + return err; + + data->extend = data->extstart + + grub_le_to_cpu64 (data->extent->size); + if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR + && (char *) &data->extent + elemsize + >= (char *) &data->extent->filled + + sizeof (data->extent->filled)) + data->extend = data->extstart + + grub_le_to_cpu64 (data->extent->filled); + + grub_dprintf ("btrfs", "extent 0x%" PRIxGRUB_UINT64_T "+0x%" + PRIxGRUB_UINT64_T " (0x%" + PRIxGRUB_UINT64_T ")\n", + grub_le_to_cpu64 (key_out.offset), + grub_le_to_cpu64 (data->extent->size), + grub_le_to_cpu64 (data->extent->filled)); + if (data->extend <= pos) + { + grub_error (GRUB_ERR_BAD_FS, "extent not found"); + return -1; + } + } + csize = data->extend - pos; + extoff = pos - data->extstart; + if (csize > len) + csize = len; + + if (data->extent->encryption) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "encryption not supported"); + return -1; + } + + if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE + && data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "compression type 0x%x not supported", + data->extent->compression); + return -1; + } + + if (data->extent->encoding) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "encoding not supported"); + return -1; + } + + switch (data->extent->type) + { + case GRUB_BTRFS_EXTENT_INLINE: + if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB) + { + if (grub_zlib_decompress (data->extent->inl, data->extsize - + ((grub_uint8_t *) data->extent->inl + - (grub_uint8_t *) data->extent), + extoff, buf, csize) + != (grub_ssize_t) csize) + return -1; + } + else + grub_memcpy (buf, data->extent->inl + extoff, csize); + break; + case GRUB_BTRFS_EXTENT_REGULAR: + if (!data->extent->laddr) + { + grub_memset (buf, 0, csize); + break; + } + if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB) + { + char *tmp; + grub_uint64_t zsize; + zsize = grub_le_to_cpu64 (data->extent->compressed_size); + tmp = grub_malloc (zsize); + if (!tmp) + return -1; + err = grub_btrfs_read_logical (data, + grub_le_to_cpu64 (data->extent->laddr), + tmp, zsize); + if (err) + { + grub_free (tmp); + return -1; + } + if (grub_zlib_decompress (tmp, zsize, extoff + + grub_le_to_cpu64 (data->extent->offset), + buf, csize) != (grub_ssize_t) csize) + { + grub_free (tmp); + return -1; + } + grub_free (tmp); + break; + } + err = grub_btrfs_read_logical (data, + grub_le_to_cpu64 (data->extent->laddr) + + grub_le_to_cpu64 (data->extent->offset) + + extoff, + buf, csize); + if (err) + return -1; + break; + default: + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported extent type 0x%x", data->extent->type); + return -1; + } + buf += csize; + pos += csize; + len -= csize; + } + return pos - pos0; } static grub_err_t -grub_btrfs_dir (grub_device_t device, - const char *path __attribute__ ((unused)), +find_path (struct grub_btrfs_data *data, + const char *path, struct grub_btrfs_key *key, + grub_uint64_t *tree, grub_uint8_t *type) +{ + const char *slash = path; + grub_err_t err; + grub_disk_addr_t elemaddr; + grub_size_t elemsize; + grub_size_t allocated = 0; + struct grub_btrfs_dir_item *direl = NULL; + struct grub_btrfs_key key_out; + int skip_default; + const char *ctoken; + grub_size_t ctokenlen; + char *path_alloc = NULL; + unsigned symlinks_max = 32; + + *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; + *tree = data->sblock.root_tree; + key->object_id = data->sblock.root_dir_objectid; + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = 0; + skip_default = 1; + + while (1) + { + if (!skip_default) + { + while (path[0] == '/') + path++; + if (!path[0]) + break; + slash = grub_strchr (path, '/'); + if (!slash) + slash = path + grub_strlen (path); + ctoken = path; + ctokenlen = slash - path; + } + else + { + ctoken = "default"; + ctokenlen = sizeof ("default") - 1; + } + + if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) + { + grub_free (path_alloc); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + } + + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen)); + + err = lower_bound (data, key, &key_out, *tree, + &elemaddr, &elemsize, NULL); + if (err) + { + grub_free (direl); + grub_free (path_alloc); + return err; + } + if (key_cmp (key, &key_out) != 0) + { + grub_free (direl); + grub_free (path_alloc); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + } + + struct grub_btrfs_dir_item *cdirel; + if (elemsize > allocated) + { + allocated = 2 * elemsize; + grub_free (direl); + direl = grub_malloc (allocated + 1); + if (!direl) + { + grub_free (path_alloc); + return grub_errno; + } + } + + err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize); + if (err) + { + grub_free (direl); + grub_free (path_alloc); + return err; + } + + for (cdirel = direl; + (grub_uint8_t *) cdirel - (grub_uint8_t *) direl + < (grub_ssize_t) elemsize; + cdirel = (void *) ((grub_uint8_t *) (direl + 1) + + grub_le_to_cpu16 (cdirel->n) + + grub_le_to_cpu16 (cdirel->m))) + { + if (ctokenlen == grub_le_to_cpu16 (cdirel->n) + && grub_memcmp (cdirel->name, ctoken, ctokenlen) == 0) + break; + } + if ((grub_uint8_t *) cdirel - (grub_uint8_t *) direl + >= (grub_ssize_t) elemsize) + { + grub_free (direl); + grub_free (path_alloc); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + } + + if (!skip_default) + path = slash; + skip_default = 0; + if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK) + { + struct grub_btrfs_inode inode; + char *tmp; + if (--symlinks_max == 0) + { + grub_free (direl); + grub_free (path_alloc); + return grub_error (GRUB_ERR_SYMLINK_LOOP, + "too deep nesting of symlinks"); + } + + err = grub_btrfs_read_inode (data, &inode, + cdirel->key.object_id, *tree); + if (err) + { + grub_free (direl); + grub_free (path_alloc); + return err; + } + tmp = grub_malloc (grub_le_to_cpu64 (inode.size) + + grub_strlen (path) + 1); + if (!tmp) + { + grub_free (direl); + grub_free (path_alloc); + return grub_errno; + } + + if (grub_btrfs_extent_read (data, cdirel->key.object_id, + *tree, 0, tmp, + grub_le_to_cpu64 (inode.size)) + != (grub_ssize_t) grub_le_to_cpu64 (inode.size)) + { + grub_free (direl); + grub_free (path_alloc); + grub_free (tmp); + return grub_errno; + } + grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path, + grub_strlen (path) + 1); + grub_free (path_alloc); + path = path_alloc = tmp; + if (path[0] == '/') + { + *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; + *tree = data->sblock.root_tree; + key->object_id = data->sblock.root_dir_objectid; + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = 0; + skip_default = 1; + } + continue; + } + *type = cdirel->type; + + switch (cdirel->key.type) + { + case GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM: + { + struct grub_btrfs_root_item ri; + err = lower_bound (data, &cdirel->key, &key_out, + data->sblock.root_tree, + &elemaddr, &elemsize, NULL); + if (err) + { + grub_free (direl); + grub_free (path_alloc); + return err; + } + if (cdirel->key.object_id != key_out.object_id + || cdirel->key.type != key_out.type) + { + grub_free (direl); + grub_free (path_alloc); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + } + err = grub_btrfs_read_logical (data, elemaddr, + &ri, sizeof (ri)); + if (err) + { + grub_free (direl); + grub_free (path_alloc); + return err; + } + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = 0; + key->object_id = GRUB_BTRFS_OBJECT_ID_CHUNK; + *tree = grub_le_to_cpu64 (ri.tree); + break; + } + case GRUB_BTRFS_ITEM_TYPE_INODE_ITEM: + if (*slash && *type == GRUB_BTRFS_DIR_ITEM_TYPE_REGULAR) + { + grub_free (direl); + grub_free (path_alloc); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + } + *key = cdirel->key; + if (*type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + break; + default: + grub_free (path_alloc); + grub_free (direl); + return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x", + cdirel->key.type); + } + } + + grub_free (direl); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_btrfs_dir (grub_device_t device, const char *path, int (*hook) (const char *filename, - const struct grub_dirhook_info *info) - __attribute__ ((unused))) + const struct grub_dirhook_info *info)) { - struct grub_btrfs_data *data = grub_btrfs_mount (device->disk); - if (grub_errno) + struct grub_btrfs_data *data = grub_btrfs_mount (device); + struct grub_btrfs_key key_in, key_out; + grub_err_t err; + grub_disk_addr_t elemaddr; + grub_size_t elemsize; + grub_size_t allocated = 0; + struct grub_btrfs_dir_item *direl = NULL; + struct grub_btrfs_leaf_descriptor desc; + int r = 0; + grub_uint64_t tree; + grub_uint8_t type; + + if (!data) return grub_errno; - grub_free (data); + err = find_path (data, path, &key_in, &tree, &type); + if (err) + return err; + if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + + err = lower_bound (data, &key_in, &key_out, tree, + &elemaddr, &elemsize, &desc); + if (err) + return err; + if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM + || key_out.object_id != key_in.object_id) + { + r = next (data, &desc, &elemaddr, &elemsize, &key_out); + if (r <= 0) + { + free_iterator (&desc); + return -r; + } + } + do + { + struct grub_btrfs_dir_item *cdirel; + if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM + || key_out.object_id != key_in.object_id) + { + r = 0; + break; + } + if (elemsize > allocated) + { + allocated = 2 * elemsize; + grub_free (direl); + direl = grub_malloc (allocated + 1); + if (!direl) + { + free_iterator (&desc); + return grub_errno; + } + } + + err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize); + if (err) + return err; + + for (cdirel = direl; + (grub_uint8_t *) cdirel - (grub_uint8_t *) direl + < (grub_ssize_t) elemsize; + cdirel = (void *) ((grub_uint8_t *) (direl + 1) + + grub_le_to_cpu16 (cdirel->n) + + grub_le_to_cpu16 (cdirel->m))) + { + char c; + struct grub_btrfs_inode inode; + struct grub_dirhook_info info; + err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id, + tree); + grub_memset (&info, 0, sizeof (info)); + if (err) + grub_errno = GRUB_ERR_NONE; + else + { + info.mtime = inode.mtime.sec; + info.mtimeset = 1; + } + c = cdirel->name[grub_le_to_cpu16 (cdirel->n)]; + cdirel->name[grub_le_to_cpu16 (cdirel->n)] = 0; + info.dir = (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY); + if (hook (cdirel->name, &info)) + goto out; + cdirel->name[grub_le_to_cpu16 (cdirel->n)] = c; + } + r = next (data, &desc, &elemaddr, &elemsize, &key_out); + } + while (r > 0); + + out: + grub_free (direl); + + free_iterator (&desc); + grub_btrfs_unmount (data); + + return -r; +} + +static grub_err_t +grub_btrfs_open (struct grub_file *file, const char *name) +{ + struct grub_btrfs_data *data = grub_btrfs_mount (file->device); + grub_err_t err; + struct grub_btrfs_inode inode; + grub_uint8_t type; + struct grub_btrfs_key key_in; + + if (!data) + return grub_errno; + + err = find_path (data, name, &key_in, &data->tree, &type); + if (err) + { + grub_btrfs_unmount (data); + return err; + } + if (type != GRUB_BTRFS_DIR_ITEM_TYPE_REGULAR) + { + grub_btrfs_unmount (data); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file"); + } + + data->inode = key_in.object_id; + err = grub_btrfs_read_inode (data, &inode, data->inode, data->tree); + if (err) + { + grub_btrfs_unmount (data); + return err; + } + + file->data = data; + file->size = grub_le_to_cpu64 (inode.size); + + return err; +} + +static grub_err_t +grub_btrfs_close (grub_file_t file) +{ + grub_btrfs_unmount (file->data); return GRUB_ERR_NONE; } +static grub_ssize_t +grub_btrfs_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_btrfs_data *data = file->data; + + return grub_btrfs_extent_read (data, data->inode, + data->tree, file->offset, buf, len); +} + static grub_err_t grub_btrfs_uuid (grub_device_t device, char **uuid) { @@ -97,7 +1429,7 @@ grub_btrfs_uuid (grub_device_t device, char **uuid) *uuid = NULL; - data = grub_btrfs_mount (device->disk); + data = grub_btrfs_mount (device); if (! data) return grub_errno; @@ -111,7 +1443,25 @@ grub_btrfs_uuid (grub_device_t device, char **uuid) grub_be_to_cpu16 (data->sblock.uuid[6]), grub_be_to_cpu16 (data->sblock.uuid[7])); - grub_free (data); + grub_btrfs_unmount (data); + + return grub_errno; +} + +static grub_err_t +grub_btrfs_label (grub_device_t device, char **label) +{ + struct grub_btrfs_data *data; + + *label = NULL; + + data = grub_btrfs_mount (device); + if (! data) + return grub_errno; + + *label = grub_strndup (data->sblock.label, sizeof (data->sblock.label)); + + grub_btrfs_unmount (data); return grub_errno; } @@ -121,7 +1471,13 @@ static struct grub_fs grub_btrfs_fs = .name = "btrfs", .dir = grub_btrfs_dir, .open = grub_btrfs_open, + .read = grub_btrfs_read, + .close = grub_btrfs_close, .uuid = grub_btrfs_uuid, + .label = grub_btrfs_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, +#endif }; GRUB_MOD_INIT(btrfs) diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 2c92404c3..a7ccfbded 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #ifndef MODE_USTAR /* cpio support */ #define MAGIC_BCPIO 070707 diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index 9d7bbfd36..0fdf151a2 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -51,6 +51,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* Log2 size of ext2 block in 512 blocks. */ #define LOG2_EXT2_BLOCK_SIZE(data) \ (grub_le_to_cpu32 (data->sblock.log2_block_size) + 1) diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 89050943c..76b9c52d7 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_FAT_DIR_ENTRY_SIZE 32 #define GRUB_FAT_ATTR_READ_ONLY 0x01 diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index d0b1e493e..f879885ac 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -22,7 +22,9 @@ #include #include #include +#include +GRUB_MOD_LICENSE ("GPLv3+"); /* Lookup the node PATH. The node ROOTNODE describes the root of the directory tree. The node found is returned in FOUNDNODE, which is diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index cef856326..1f67ea155 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -29,6 +29,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_HFS_SBLOCK 2 #define GRUB_HFS_EMBED_HFSPLUS_SIG 0x482B diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 7d7115ce3..304b32126 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -30,6 +30,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_HFSPLUS_MAGIC 0x482B #define GRUB_HFSPLUSX_MAGIC 0x4858 #define GRUB_HFSPLUS_SBLOCK 2 diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index f72249d20..a9a17fef8 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_ISO9660_FSTYPE_DIR 0040000 #define GRUB_ISO9660_FSTYPE_REG 0100000 #define GRUB_ISO9660_FSTYPE_SYMLINK 0120000 diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 76ef2e540..72e6adc74 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_JFS_MAX_SYMLNK_CNT 8 #define GRUB_JFS_FILETYPE_MASK 0170000 #define GRUB_JFS_FILETYPE_REG 0100000 @@ -217,12 +219,12 @@ struct grub_jfs_diropen struct grub_jfs_tree_dir header; struct grub_jfs_leaf_dirent dirent[0]; struct grub_jfs_leaf_next_dirent next_dirent[0]; - char sorted[0]; + grub_uint8_t sorted[0]; } *dirpage __attribute__ ((packed)); struct grub_jfs_data *data; struct grub_jfs_inode *inode; int count; - char *sorted; + grub_uint8_t *sorted; struct grub_jfs_leaf_dirent *leaf; struct grub_jfs_leaf_next_dirent *next_leaf; @@ -234,13 +236,13 @@ struct grub_jfs_diropen static grub_dl_t my_mod; -static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, int ino); +static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino); /* Get the block number for the block BLK in the node INODE in the mounted filesystem DATA. */ -static int +static grub_int64_t grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode, - unsigned int blk) + grub_uint64_t blk) { auto int getblk (struct grub_jfs_treehead *treehead, struct grub_jfs_tree_extent *extents); @@ -294,15 +296,15 @@ grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode, static grub_err_t -grub_jfs_read_inode (struct grub_jfs_data *data, int ino, +grub_jfs_read_inode (struct grub_jfs_data *data, grub_uint32_t ino, struct grub_jfs_inode *inode) { struct grub_jfs_iag iag; - int iagnum = ino / 4096; - int inoext = (ino % 4096) / 32; - int inonum = (ino % 4096) % 32; - grub_uint32_t iagblk; - grub_uint32_t inoblk; + grub_uint32_t iagnum = ino / 4096; + unsigned inoext = (ino % 4096) / 32; + unsigned inonum = (ino % 4096) % 32; + grub_uint64_t iagblk; + grub_uint64_t inoblk; iagblk = grub_jfs_blkno (data, &data->fileset, iagnum + 1); if (grub_errno) @@ -348,6 +350,13 @@ grub_jfs_mount (grub_disk_t disk) goto fail; } + if (grub_le_to_cpu32 (data->sblock.blksz) + != (1U << grub_le_to_cpu16 (data->sblock.log2_blksz))) + { + grub_error (GRUB_ERR_BAD_FS, "not a JFS filesystem"); + goto fail; + } + data->disk = disk; data->pos = 0; data->linknest = 0; @@ -374,7 +383,7 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode) { struct grub_jfs_internal_dirent *de; struct grub_jfs_diropen *diro; - int blk; + grub_disk_addr_t blk; de = (struct grub_jfs_internal_dirent *) inode->dir.dirents; @@ -397,7 +406,7 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode) { diro->leaf = inode->dir.dirents; diro->next_leaf = (struct grub_jfs_leaf_next_dirent *) de; - diro->sorted = (char *) (inode->dir.header.sorted); + diro->sorted = inode->dir.header.sorted; diro->count = inode->dir.header.count; return diro; @@ -475,7 +484,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) /* The last node, read in more. */ if (diro->index == diro->count) { - unsigned int next; + grub_disk_addr_t next; /* If the inode contains the entry tree or if this was the last node, there is nothing to read. */ @@ -499,7 +508,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) diro->index = 0; } - leaf = &diro->leaf[(int) diro->sorted[diro->index]]; + leaf = &diro->leaf[diro->sorted[diro->index]]; next_leaf = &diro->next_leaf[diro->index]; len = leaf->len; @@ -540,21 +549,21 @@ static grub_ssize_t grub_jfs_read_file (struct grub_jfs_data *data, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_uint64_t pos, grub_size_t len, char *buf) { - int i; - int blockcnt; + grub_uint64_t i; + grub_uint64_t blockcnt; - blockcnt = ((len + pos + grub_le_to_cpu32 (data->sblock.blksz) - 1) - / grub_le_to_cpu32 (data->sblock.blksz)); + blockcnt = (len + pos + grub_le_to_cpu32 (data->sblock.blksz) - 1) + >> grub_le_to_cpu16 (data->sblock.log2_blksz); - for (i = pos / grub_le_to_cpu32 (data->sblock.blksz); i < blockcnt; i++) + for (i = pos >> grub_le_to_cpu16 (data->sblock.log2_blksz); i < blockcnt; i++) { - int blknr; - int blockoff = pos % grub_le_to_cpu32 (data->sblock.blksz); - int blockend = grub_le_to_cpu32 (data->sblock.blksz); + grub_disk_addr_t blknr; + grub_uint32_t blockoff = pos & (grub_le_to_cpu32 (data->sblock.blksz) - 1); + grub_uint32_t blockend = grub_le_to_cpu32 (data->sblock.blksz); - int skipfirst = 0; + grub_uint64_t skipfirst = 0; blknr = grub_jfs_blkno (data, &data->currinode, i); if (grub_errno) @@ -563,14 +572,14 @@ grub_jfs_read_file (struct grub_jfs_data *data, /* Last block. */ if (i == blockcnt - 1) { - blockend = (len + pos) % grub_le_to_cpu32 (data->sblock.blksz); + blockend = (len + pos) & (grub_le_to_cpu32 (data->sblock.blksz) - 1); if (!blockend) blockend = grub_le_to_cpu32 (data->sblock.blksz); } /* First block. */ - if (i == (pos / (int) grub_le_to_cpu32 (data->sblock.blksz))) + if (i == (pos >> grub_le_to_cpu16 (data->sblock.log2_blksz))) { skipfirst = blockoff; blockend -= skipfirst; @@ -642,8 +651,8 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path) pathname. */ if (!grub_strcmp (name, diro->name)) { - int ino = diro->ino; - int dirino = grub_le_to_cpu32 (data->currinode.inode); + grub_uint32_t ino = diro->ino; + grub_uint32_t dirino = grub_le_to_cpu32 (data->currinode.inode); grub_jfs_closedir (diro); diro = 0; @@ -687,9 +696,9 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path) static grub_err_t -grub_jfs_lookup_symlink (struct grub_jfs_data *data, int ino) +grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) { - int size = grub_le_to_cpu64 (data->currinode.size); + grub_uint64_t size = grub_le_to_cpu64 (data->currinode.size); char symlink[size + 1]; if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT) diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 679e1ec51..523e6e616 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #ifdef MODE_MINIX2 #define GRUB_MINIX_MAGIC 0x2468 #define GRUB_MINIX_MAGIC_30 0x2478 diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index e529775f4..4c8d7633c 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -35,6 +35,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define NILFS_INODE_BMAP_SIZE 7 #define NILFS_SUPORT_REV 2 diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index 414f6513d..e01ce34c2 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; ntfscomp_func_t grub_ntfscomp_func; diff --git a/grub-core/fs/ntfscomp.c b/grub-core/fs/ntfscomp.c index c29979edc..d2893cb99 100644 --- a/grub-core/fs/ntfscomp.c +++ b/grub-core/fs/ntfscomp.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t decomp_nextvcn (struct grub_ntfs_comp *cc) { diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index e92279554..f2984f845 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -39,6 +39,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define MIN(a, b) \ ({ typeof (a) _a = (a); \ typeof (b) _b = (b); \ diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index b49420de1..455743117 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* The common header for a block. */ struct grub_sfs_bheader { diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 1672aab1b..5842d5d12 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_UDF_MAX_PDS 2 #define GRUB_UDF_MAX_PMS 6 diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index 2b1021db6..86fe8af65 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #ifdef MODE_UFS2 #define GRUB_UFS_MAGIC 0x19540119 #else diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 9f8dc28de..2eadc3768 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define XFS_INODE_EXTENTS 9 #define XFS_INODE_FORMAT_INO 1 diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 8e83ea0b5..8d86cf9e5 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -52,6 +52,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define ZPOOL_PROP_BOOTFS "bootfs" #define MIN(a,b) (((a) < (b)) ? (a) : (b)) diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c index 224a97792..1968ed554 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static inline void print_tabs (int n) { diff --git a/grub-core/gentrigtables.c b/grub-core/gentrigtables.c index bef2b083c..8c039570d 100644 --- a/grub-core/gentrigtables.c +++ b/grub-core/gentrigtables.c @@ -30,6 +30,14 @@ main (int argc __attribute__ ((unused)), int i; printf ("#include \n"); + printf ("#include \n"); + printf ("\n"); + + printf ("/* Under copyright legislature such automated output isn't\n"); + printf ("covered by any copyright. Hence it's public domain. Public\n"); + printf ("domain works can be dual-licenced with any license. */\n"); + printf ("GRUB_MOD_LICENSE (\"GPLv3+\");"); + printf ("GRUB_MOD_DUAL_LICENSE (\"Public Domain\");"); #define TAB(op) \ printf ("grub_int16_t grub_trig_" #op "tab[] =\n{"); \ diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c index 84937f19b..cca8b901f 100644 --- a/grub-core/gettext/gettext.c +++ b/grub-core/gettext/gettext.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* .mo file information from: http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html . diff --git a/grub-core/gfxmenu/gfxmenu.c b/grub-core/gfxmenu/gfxmenu.c index 76d83c44b..2f210e02b 100644 --- a/grub-core/gfxmenu/gfxmenu.c +++ b/grub-core/gfxmenu/gfxmenu.c @@ -37,6 +37,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_gfxmenu_view_t cached_view; static void @@ -56,30 +58,15 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) theme_path = grub_env_get ("theme"); if (! theme_path) - { - grub_error_push (); - grub_gfxterm_fullscreen (); - grub_error_pop (); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified"); - } + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified"); instance = grub_zalloc (sizeof (*instance)); if (!instance) - { - grub_error_push (); - grub_gfxterm_fullscreen (); - grub_error_pop (); - return grub_errno; - } + return grub_errno; err = grub_video_get_info (&mode_info); if (err) - { - grub_error_push (); - grub_gfxterm_fullscreen (); - grub_error_pop (); - return err; - } + return err; if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0 || cached_view->screen.width != mode_info.width @@ -94,9 +81,6 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) if (! cached_view) { grub_free (instance); - grub_error_push (); - grub_gfxterm_fullscreen (); - grub_error_pop (); return grub_errno; } diff --git a/grub-core/gfxmenu/gui_image.c b/grub-core/gfxmenu/gui_image.c index 3988f4ba8..60e4a46de 100644 --- a/grub-core/gfxmenu/gui_image.c +++ b/grub-core/gfxmenu/gui_image.c @@ -101,6 +101,9 @@ image_get_parent (void *vself) static grub_err_t rescale_image (grub_gui_image_t self) { + signed width; + signed height; + if (! self->raw_bitmap) { if (self->bitmap) @@ -111,12 +114,12 @@ rescale_image (grub_gui_image_t self) return grub_errno; } - unsigned width = self->bounds.width; - unsigned height = self->bounds.height; + width = self->bounds.width; + height = self->bounds.height; if (self->bitmap - && (grub_video_bitmap_get_width (self->bitmap) == width) - && (grub_video_bitmap_get_height (self->bitmap) == height)) + && ((signed) grub_video_bitmap_get_width (self->bitmap) == width) + && ((signed) grub_video_bitmap_get_height (self->bitmap) == height)) { /* Nothing to do; already the right size. */ return grub_errno; @@ -131,15 +134,15 @@ rescale_image (grub_gui_image_t self) /* Create a scaled bitmap, unless the requested size is the same as the raw size -- in that case a reference is made. */ - if (grub_video_bitmap_get_width (self->raw_bitmap) == width - && grub_video_bitmap_get_height (self->raw_bitmap) == height) + if ((signed) grub_video_bitmap_get_width (self->raw_bitmap) == width + && (signed) grub_video_bitmap_get_height (self->raw_bitmap) == height) { self->bitmap = self->raw_bitmap; return grub_errno; } /* Don't scale to an invalid size. */ - if (width == 0 || height == 0) + if (width <= 0 || height <= 0) return grub_errno; /* Create the scaled bitmap. */ diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c index b6b07dfd6..e5d6fc2a1 100644 --- a/grub-core/gfxmenu/gui_list.c +++ b/grub-core/gfxmenu/gui_list.c @@ -248,8 +248,10 @@ draw_menu (list_impl_t self, int num_shown_items) if (is_selected) { - selbox->set_content_size (selbox, oviewport.width - 2 * boxpad - 2, - item_height - 1); + int cwidth = oviewport.width - 2 * boxpad - 2; + if (selbox->get_border_width) + cwidth -= selbox->get_border_width (selbox); + selbox->set_content_size (selbox, cwidth, item_height - 1); selbox->draw (selbox, 0, item_top - sel_toppad); } diff --git a/grub-core/gfxmenu/icon_manager.c b/grub-core/gfxmenu/icon_manager.c index 0c304ede0..6990d05d4 100644 --- a/grub-core/gfxmenu/icon_manager.c +++ b/grub-core/gfxmenu/icon_manager.c @@ -257,7 +257,7 @@ grub_gfxmenu_icon_manager_get_icon (grub_gfxmenu_icon_manager_t mgr, /* Try each class in succession. */ icon = 0; - for (c = entry->classes->next; c && ! icon; c = c->next) + for (c = entry->classes; c && ! icon; c = c->next) icon = get_icon_by_class (mgr, c->name); return icon; } diff --git a/grub-core/gfxmenu/widget-box.c b/grub-core/gfxmenu/widget-box.c index 244fe1e6c..41ca7f536 100644 --- a/grub-core/gfxmenu/widget-box.c +++ b/grub-core/gfxmenu/widget-box.c @@ -178,6 +178,13 @@ set_content_size (grub_gfxmenu_box_t self, return; } +static int +get_border_width (grub_gfxmenu_box_t self) +{ + return (get_width (self->raw_pixmaps[BOX_PIXMAP_E]) + + get_width (self->raw_pixmaps[BOX_PIXMAP_W])); +} + static int get_left_pad (grub_gfxmenu_box_t self) { @@ -288,6 +295,8 @@ grub_gfxmenu_create_box (const char *pixmaps_prefix, box->draw = draw; box->set_content_size = set_content_size; + box->get_border_width = get_border_width; + box->get_left_pad = get_left_pad; box->get_top_pad = get_top_pad; box->get_right_pad = get_right_pad; diff --git a/grub-core/gnulib/argp-parse.c b/grub-core/gnulib/argp-parse.c index a1cbf884e..9c054653c 100644 --- a/grub-core/gnulib/argp-parse.c +++ b/grub-core/gnulib/argp-parse.c @@ -935,7 +935,7 @@ weak_alias (__argp_parse, argp_parse) void * __argp_input (const struct argp *argp, const struct argp_state *state) { - if (state) + if (state && state->pstate) { struct group *group; struct parser *parser = state->pstate; diff --git a/grub-core/hello/hello.c b/grub-core/hello/hello.c index 77c4c96b1..2c9e90f72 100644 --- a/grub-core/hello/hello.c +++ b/grub-core/hello/hello.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_cmd_hello (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/grub-core/hook/datehook.c b/grub-core/hook/datehook.c index d855311d3..f64fac074 100644 --- a/grub-core/hook/datehook.c +++ b/grub-core/hook/datehook.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static char *grub_datetime_names[] = { "YEAR", diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c index 891fb78e9..3b456c1d2 100644 --- a/grub-core/io/bufio.c +++ b/grub-core/io/bufio.c @@ -23,6 +23,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_BUFIO_DEF_SIZE 8192 #define GRUB_BUFIO_MAX_SIZE 1048576 diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c index 47df23833..1397a7286 100644 --- a/grub-core/io/gzio.c +++ b/grub-core/io/gzio.c @@ -41,6 +41,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); /* * Window Size @@ -58,6 +61,9 @@ struct grub_gzio { /* The underlying file object. */ grub_file_t file; + /* If input is in memory following fields are used instead of file. */ + grub_size_t mem_input_size, mem_input_off; + grub_uint8_t *mem_input; /* The offset at which the data starts in the underlying file. */ grub_off_t data_offset; /* The type of current block. */ @@ -100,7 +106,7 @@ typedef struct grub_gzio *grub_gzio_t; static struct grub_fs grub_gzio_fs; /* Function prototypes */ -static void initialize_tables (grub_file_t file); +static void initialize_tables (grub_gzio_t); /* Eat variable-length header fields. */ static int @@ -162,7 +168,7 @@ typedef unsigned short ush; typedef unsigned long ulg; static int -test_header (grub_file_t file) +test_gzip_header (grub_file_t file) { struct { grub_uint16_t magic; @@ -225,7 +231,7 @@ test_header (grub_file_t file) file->size = grub_le_to_cpu32 (orig_len); } - initialize_tables (file); + initialize_tables (gzio); return 1; } @@ -365,13 +371,18 @@ static ush mask_bits[] = 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; -#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(file))<>=(n);k-=(n);} while (0) static int -get_byte (grub_file_t file) +get_byte (grub_gzio_t gzio) { - grub_gzio_t gzio = file->data; + if (gzio->mem_input) + { + if (gzio->mem_input_off < gzio->mem_input_size) + return gzio->mem_input[gzio->mem_input_off++]; + return 0; + } if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset || gzio->inbuf_d == INBUFSIZ) @@ -383,11 +394,26 @@ get_byte (grub_file_t file) return gzio->inbuf[gzio->inbuf_d++]; } +static void +gzio_seek (grub_gzio_t gzio, grub_off_t off) +{ + if (gzio->mem_input) + { + if (off > gzio->mem_input_size) + grub_error (GRUB_ERR_OUT_OF_RANGE, + "attempt to seek outside of the file"); + else + gzio->mem_input_off = gzio->data_offset; + } + else + grub_file_seek (gzio->file, off); +} + /* more function prototypes */ static int huft_build (unsigned *, unsigned, unsigned, ush *, ush *, struct huft **, int *); static int huft_free (struct huft *); -static int inflate_codes_in_window (grub_file_t); +static int inflate_codes_in_window (grub_gzio_t); /* Given a list of code lengths and a maximum table size, make a set of @@ -614,7 +640,7 @@ huft_free (struct huft *t) */ static int -inflate_codes_in_window (grub_file_t file) +inflate_codes_in_window (grub_gzio_t gzio) { register unsigned e; /* table entry flag/number of extra bits */ unsigned n, d; /* length and index for copy */ @@ -623,7 +649,6 @@ inflate_codes_in_window (grub_file_t file) unsigned ml, md; /* masks for bl and bd bits */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ - grub_gzio_t gzio = file->data; /* make local copies of globals */ d = gzio->inflate_d; @@ -751,11 +776,10 @@ inflate_codes_in_window (grub_file_t file) /* get header for an inflated type 0 (stored) block. */ static void -init_stored_block (grub_file_t file) +init_stored_block (grub_gzio_t gzio) { register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ - grub_gzio_t gzio = file->data; /* make local copies of globals */ b = gzio->bb; /* initialize bit buffer */ @@ -785,11 +809,10 @@ init_stored_block (grub_file_t file) Huffman tables. */ static void -init_fixed_block (grub_file_t file) +init_fixed_block (grub_gzio_t gzio) { int i; /* temporary variable */ unsigned l[288]; /* length list for huft_build */ - grub_gzio_t gzio = file->data; /* set up literal table */ for (i = 0; i < 144; i++) @@ -832,7 +855,7 @@ init_fixed_block (grub_file_t file) /* get header for an inflated type 2 (dynamic Huffman codes) block. */ static void -init_dynamic_block (grub_file_t file) +init_dynamic_block (grub_gzio_t gzio) { int i; /* temporary variables */ unsigned j; @@ -845,7 +868,6 @@ init_dynamic_block (grub_file_t file) unsigned ll[286 + 30]; /* literal/length and distance code lengths */ register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ - grub_gzio_t gzio = file->data; /* make local bit buffer */ b = gzio->bb; @@ -976,11 +998,10 @@ init_dynamic_block (grub_file_t file) static void -get_new_block (grub_file_t file) +get_new_block (grub_gzio_t gzio) { register ulg b; /* bit buffer */ register unsigned k; /* number of bits in bit buffer */ - grub_gzio_t gzio = file->data; /* make local bit buffer */ b = gzio->bb; @@ -1003,13 +1024,13 @@ get_new_block (grub_file_t file) switch (gzio->block_type) { case INFLATE_STORED: - init_stored_block (file); + init_stored_block (gzio); break; case INFLATE_FIXED: - init_fixed_block (file); + init_fixed_block (gzio); break; case INFLATE_DYNAMIC: - init_dynamic_block (file); + init_dynamic_block (gzio); break; default: break; @@ -1018,10 +1039,8 @@ get_new_block (grub_file_t file) static void -inflate_window (grub_file_t file) +inflate_window (grub_gzio_t gzio) { - grub_gzio_t gzio = file->data; - /* initialize window */ gzio->wp = 0; @@ -1036,7 +1055,7 @@ inflate_window (grub_file_t file) if (gzio->last_block) break; - get_new_block (file); + get_new_block (gzio); } if (gzio->block_type > INFLATE_DYNAMIC) @@ -1059,7 +1078,7 @@ inflate_window (grub_file_t file) while (gzio->block_len && w < WSIZE && grub_errno == GRUB_ERR_NONE) { - gzio->slide[w++] = get_byte (file); + gzio->slide[w++] = get_byte (gzio); gzio->block_len--; } @@ -1072,7 +1091,7 @@ inflate_window (grub_file_t file) * Expand other kind of block. */ - if (inflate_codes_in_window (file)) + if (inflate_codes_in_window (gzio)) { huft_free (gzio->tl); huft_free (gzio->td); @@ -1088,12 +1107,10 @@ inflate_window (grub_file_t file) static void -initialize_tables (grub_file_t file) +initialize_tables (grub_gzio_t gzio) { - grub_gzio_t gzio = file->data; - gzio->saved_offset = 0; - grub_file_seek (gzio->file, gzio->data_offset); + gzio_seek (gzio, gzio->data_offset); /* Initialize the bit buffer. */ gzio->bk = 0; @@ -1138,7 +1155,7 @@ grub_gzio_open (grub_file_t io) file->fs = &grub_gzio_fs; file->not_easily_seekable = 1; - if (! test_header (file)) + if (! test_gzip_header (file)) { grub_free (gzio); grub_free (file); @@ -1154,16 +1171,49 @@ grub_gzio_open (grub_file_t io) return file; } +static int +test_zlib_header (grub_gzio_t gzio) +{ + grub_uint8_t cmf, flg; + + cmf = get_byte (gzio); + flg = get_byte (gzio); + + /* Check that compression method is DEFLATE. */ + if ((cmf & 0xf) != DEFLATED) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format"); + return 0; + } + + if ((cmf * 256 + flg) % 31) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format"); + return 0; + } + + /* Dictionary isn't supported. */ + if (flg & 0x20) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format"); + return 0; + } + + gzio->data_offset = 2; + initialize_tables (gzio); + + return 1; +} + static grub_ssize_t -grub_gzio_read (grub_file_t file, char *buf, grub_size_t len) +grub_gzio_read_real (grub_gzio_t gzio, grub_off_t offset, + char *buf, grub_size_t len) { grub_ssize_t ret = 0; - grub_gzio_t gzio = file->data; - grub_off_t offset; /* Do we reset decompression to the beginning of the file? */ - if (gzio->saved_offset > file->offset + WSIZE) - initialize_tables (file); + if (gzio->saved_offset > offset + WSIZE) + initialize_tables (gzio); /* * This loop operates upon uncompressed data only. The only @@ -1171,15 +1221,13 @@ grub_gzio_read (grub_file_t file, char *buf, grub_size_t len) * window is within the range of data it needs. */ - offset = file->offset; - while (len > 0 && grub_errno == GRUB_ERR_NONE) { register grub_size_t size; register char *srcaddr; while (offset >= gzio->saved_offset) - inflate_window (file); + inflate_window (gzio); srcaddr = (char *) ((offset & (WSIZE - 1)) + gzio->slide); size = gzio->saved_offset - offset; @@ -1200,6 +1248,12 @@ grub_gzio_read (grub_file_t file, char *buf, grub_size_t len) return ret; } +static grub_ssize_t +grub_gzio_read (grub_file_t file, char *buf, grub_size_t len) +{ + return grub_gzio_read_real (file->data, file->offset, buf, len); +} + /* Release everything, including the underlying file object. */ static grub_err_t grub_gzio_close (grub_file_t file) @@ -1217,6 +1271,33 @@ grub_gzio_close (grub_file_t file) return grub_errno; } +grub_ssize_t +grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off, + char *outbuf, grub_size_t outsize) +{ + grub_gzio_t gzio = 0; + grub_ssize_t ret; + + gzio = grub_zalloc (sizeof (*gzio)); + if (! gzio) + return -1; + gzio->mem_input = (grub_uint8_t *) inbuf; + gzio->mem_input_size = insize; + gzio->mem_input_off = 0; + + if (!test_zlib_header (gzio)) + { + grub_free (gzio); + return -1; + } + + ret = grub_gzio_read_real (gzio, off, outbuf, outsize); + grub_free (gzio); + + /* FIXME: Check Adler. */ + return ret; +} + static struct grub_fs grub_gzio_fs = diff --git a/grub-core/io/xzio.c b/grub-core/io/xzio.c index 3daf6a3fe..1f42cd242 100644 --- a/grub-core/io/xzio.c +++ b/grub-core/io/xzio.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #include "xz.h" #include "xz_stream.h" diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 02d785b9b..c5e2888cd 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -373,6 +373,38 @@ grub_dl_call_init (grub_dl_t mod) (mod->init) (mod); } +/* Me, Vladimir Serbinenko, hereby I add this module check as per new + GNU module policy. Note that this license check is informative only. + Modules have to be licensed under GPLv3 or GPLv3+ (optionally + multi-licensed under other licences as well) independently of the + presence of this check and solely by linking (module loading in GRUB + constitutes linking) and GRUB core being licensed under GPLv3+. + Be sure to understand your license obligations. +*/ +static grub_err_t +grub_dl_check_license (Elf_Ehdr *e) +{ + Elf_Shdr *s; + const char *str; + unsigned i; + + s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); + str = (char *) e + s->sh_offset; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (grub_strcmp (str + s->sh_name, ".module_license") == 0) + { + if (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0) + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license"); +} + static grub_err_t grub_dl_resolve_name (grub_dl_t mod, Elf_Ehdr *e) { @@ -519,7 +551,16 @@ grub_dl_load_core (void *addr, grub_size_t size) mod->ref_count = 1; grub_dprintf ("modules", "relocating to %p\n", mod); - if (grub_dl_resolve_name (mod, e) + /* Me, Vladimir Serbinenko, hereby I add this module check as per new + GNU module policy. Note that this license check is informative only. + Modules have to be licensed under GPLv3 or GPLv3+ (optionally + multi-licensed under other licences as well) independently of the + presence of this check and solely by linking (module loading in GRUB + constitutes linking) and GRUB core being licensed under GPLv3+. + Be sure to understand your license obligations. + */ + if (grub_dl_check_license (e) + || grub_dl_resolve_name (mod, e) || grub_dl_resolve_dependencies (mod, e) || grub_dl_load_segments (mod, e) || grub_dl_resolve_symbols (mod, e) diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c index 56218b4e4..9c7b8cec2 100644 --- a/grub-core/kern/elf.c +++ b/grub-core/kern/elf.c @@ -23,6 +23,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); /* Check if EHDR is a valid ELF header. */ static grub_err_t diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index ae066d2f8..a274f3c06 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -98,6 +98,14 @@ xgetcwd (void) #ifdef __linux__ +struct mountinfo_entry +{ + int id; + int major, minor; + char enc_root[PATH_MAX], enc_path[PATH_MAX]; + char fstype[PATH_MAX], device[PATH_MAX]; +}; + /* Statting something on a btrfs filesystem always returns a virtual device major/minor pair rather than the real underlying device, because btrfs can span multiple underlying devices (and even if it's currently only @@ -105,75 +113,120 @@ xgetcwd (void) can't deal with the multiple-device case yet, but in the meantime, we can at least cope with the single-device case by scanning /proc/self/mountinfo. */ -static char * -find_root_device_from_mountinfo (const char *dir) +char * +grub_find_root_device_from_mountinfo (const char *dir, char **relroot) { FILE *fp; char *buf = NULL; size_t len = 0; char *ret = NULL; + int entry_len = 0, entry_max = 4; + struct mountinfo_entry *entries; + struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" }; + int i; + + if (! *dir) + dir = "/"; + if (relroot) + *relroot = NULL; fp = fopen ("/proc/self/mountinfo", "r"); if (! fp) return NULL; /* fall through to other methods */ + entries = xmalloc (entry_max * sizeof (*entries)); + + /* First, build a list of relevant visible mounts. */ while (getline (&buf, &len, fp) > 0) { - int mnt_id, parent_mnt_id; - unsigned int major, minor; - char enc_root[PATH_MAX], enc_path[PATH_MAX]; + struct mountinfo_entry entry; int count; size_t enc_path_len; const char *sep; - char fstype[PATH_MAX], device[PATH_MAX]; - struct stat st; if (sscanf (buf, "%d %d %u:%u %s %s%n", - &mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path, - &count) < 6) + &entry.id, &parent_entry.id, &entry.major, &entry.minor, + entry.enc_root, entry.enc_path, &count) < 6) continue; - if (strcmp (enc_root, "/") != 0) - continue; /* only a subtree is mounted */ - - enc_path_len = strlen (enc_path); + enc_path_len = strlen (entry.enc_path); /* Check that enc_path is a prefix of dir. The prefix must either be the entire string, or end with a slash, or be immediately followed by a slash. */ - if (strncmp (dir, enc_path, enc_path_len) != 0 || + if (strncmp (dir, entry.enc_path, enc_path_len) != 0 || (enc_path_len && dir[enc_path_len - 1] != '/' && dir[enc_path_len] && dir[enc_path_len] != '/')) continue; - /* This is a parent of the requested directory. /proc/self/mountinfo - is in mount order, so it must be the closest parent we've - encountered so far. If it's virtual, return its device node; - otherwise, carry on to try to find something closer. */ - - free (ret); - ret = NULL; - - if (major != 0) - continue; /* not a virtual device */ - sep = strstr (buf + count, " - "); if (!sep) continue; sep += sizeof (" - ") - 1; - if (sscanf (sep, "%s %s", fstype, device) != 2) + if (sscanf (sep, "%s %s", entry.fstype, entry.device) != 2) continue; - if (stat (device, &st) < 0) + /* Using the mount IDs, find out where this fits in the list of + visible mount entries we've seen so far. There are three + interesting cases. Firstly, it may be inserted at the end: this is + the usual case of /foo/bar being mounted after /foo. Secondly, it + may be inserted at the start: for example, this can happen for + filesystems that are mounted before / and later moved under it. + Thirdly, it may occlude part or all of the existing filesystem + tree, in which case the end of the list needs to be pruned and this + new entry will be inserted at the end. */ + if (entry_len >= entry_max) + { + entry_max <<= 1; + entries = xrealloc (entries, entry_max * sizeof (*entries)); + } + + if (!entry_len) + { + /* Initialise list. */ + entry_len = 2; + entries[0] = parent_entry; + entries[1] = entry; + } + else + { + for (i = entry_len - 1; i >= 0; i--) + { + if (entries[i].id == parent_entry.id) + { + /* Insert at end, pruning anything previously above this. */ + entry_len = i + 2; + entries[i + 1] = entry; + break; + } + else if (i == 0 && entries[i].id == entry.id) + { + /* Insert at start. */ + entry_len++; + memmove (entries + 1, entries, + (entry_len - 1) * sizeof (*entries)); + entries[0] = parent_entry; + entries[1] = entry; + break; + } + } + } + } + + /* Now scan visible mounts for the ones we're interested in. */ + for (i = entry_len - 1; i >= 0; i--) + { + if (!*entries[i].device) continue; - if (!S_ISBLK (st.st_mode)) - continue; /* not a block device */ - - ret = strdup (device); + ret = strdup (entries[i].device); + if (relroot) + *relroot = strdup (entries[i].enc_root); + break; } free (buf); + free (entries); fclose (fp); return ret; } @@ -479,7 +532,7 @@ grub_find_device (const char *path, dev_t dev) char * grub_guess_root_device (const char *dir) { - char *os_dev; + char *os_dev = NULL; #ifdef __GNU__ file_t file; mach_port_t *ports; @@ -538,30 +591,42 @@ grub_guess_root_device (const char *dir) mach_port_deallocate (mach_task_self (), file); #else /* !__GNU__ */ struct stat st; + dev_t dev; #ifdef __linux__ - os_dev = find_root_device_from_mountinfo (dir); - if (os_dev) - return os_dev; + if (!os_dev) + os_dev = grub_find_root_device_from_mountinfo (dir, NULL); #endif /* __linux__ */ #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) - os_dev = find_root_device_from_libzfs (dir); - if (os_dev) - return os_dev; + if (!os_dev) + os_dev = find_root_device_from_libzfs (dir); #endif - if (stat (dir, &st) < 0) - grub_util_error ("cannot stat `%s'", dir); + if (os_dev) + { + if (stat (os_dev, &st) >= 0) + dev = st.st_rdev; + else + grub_util_error ("cannot stat `%s'", os_dev); + free (os_dev); + } + else + { + if (stat (dir, &st) >= 0) + dev = st.st_dev; + else + grub_util_error ("cannot stat `%s'", dir); + } #ifdef __CYGWIN__ /* Cygwin specific function. */ - os_dev = grub_find_device (dir, st.st_dev); + os_dev = grub_find_device (dir, dev); #else /* This might be truly slow, but is there any better way? */ - os_dev = grub_find_device ("/dev", st.st_dev); + os_dev = grub_find_device ("/dev", dev); #endif #endif /* !__GNU__ */ @@ -622,7 +687,7 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) #ifdef __linux__ static char * -get_mdadm_name (const char *os_dev) +get_mdadm_uuid (const char *os_dev) { int mdadm_pipe[2]; pid_t mdadm_pid; @@ -674,19 +739,21 @@ get_mdadm_name (const char *os_dev) while (getline (&buf, &len, mdadm) > 0) { - if (strncmp (buf, "MD_NAME=", sizeof ("MD_NAME=") - 1) == 0) + if (strncmp (buf, "MD_UUID=", sizeof ("MD_UUID=") - 1) == 0) { - char *name_start, *colon; + char *name_start, *ptri, *ptro; size_t name_len; free (name); - name_start = buf + sizeof ("MD_NAME=") - 1; - /* Strip off the homehost if present. */ - colon = strchr (name_start, ':'); - name = strdup (colon ? colon + 1 : name_start); - name_len = strlen (name); - if (name[name_len - 1] == '\n') - name[name_len - 1] = '\0'; + name_start = buf + sizeof ("MD_UUID=") - 1; + ptro = name = xmalloc (strlen (name_start) + 1); + for (ptri = name_start; *ptri && *ptri != '\n' && *ptri != '\r'; + ptri++) + if ((*ptri >= '0' && *ptri <= '9') + || (*ptri >= 'a' && *ptri <= 'f') + || (*ptri >= 'A' && *ptri <= 'F')) + *ptro++ = *ptri; + *ptro = 0; } } @@ -802,37 +869,26 @@ grub_util_get_grub_dev (const char *os_dev) #ifdef __linux__ { - char *mdadm_name = get_mdadm_name (os_dev); + char *mdadm_name = get_mdadm_uuid (os_dev); struct stat st; if (mdadm_name) { - char *newname; - char *q; + const char *q; - for (q = os_dev + strlen (os_dev) - 1; q >= os_dev && isdigit (*q); - q--); + for (q = os_dev + strlen (os_dev) - 1; q >= os_dev + && grub_isdigit (*q); q--); if (q >= os_dev && *q == 'p') - { - newname = xasprintf ("/dev/md/%sp%s", mdadm_name, q + 1); - if (stat (newname, &st) == 0) - { - free (grub_dev); - grub_dev = xasprintf ("md/%s,%s", mdadm_name, q + 1); - goto done; - } - free (newname); - } - newname = xasprintf ("/dev/md/%s", mdadm_name); - if (stat (newname, &st) == 0) { free (grub_dev); - grub_dev = xasprintf ("md/%s", mdadm_name); + grub_dev = xasprintf ("mduuid/%s,%s", mdadm_name, q + 1); + goto done; } + free (grub_dev); + grub_dev = xasprintf ("mduuid/%s", mdadm_name); done: - free (newname); free (mdadm_name); } } diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index d5b0439fb..63bca37ee 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -138,6 +138,7 @@ struct grub_util_biosdisk_data char *dev; int access_mode; int fd; + int is_disk; }; #ifdef __linux__ @@ -239,6 +240,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) data->dev = NULL; data->access_mode = 0; data->fd = -1; + data->is_disk = 0; /* Get the size. */ #if defined(__MINGW32__) @@ -279,6 +281,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) close (fd); goto fail; } + data->is_disk = 1; # if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if (ioctl (fd, DIOCGMEDIASIZE, &nr)) @@ -664,7 +667,18 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) { free (data->dev); if (data->fd != -1) - close (data->fd); + { + if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) + { + fsync (data->fd); +#ifdef __linux__ + if (data->is_disk) + ioctl (data->fd, BLKFLSBUF, 0); +#endif + } + + close (data->fd); + } /* Open the partition. */ grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev); @@ -675,10 +689,6 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) return -1; } - /* Flush the buffer cache to the physical disk. - XXX: This also empties the buffer cache. */ - ioctl (fd, BLKFLSBUF, 0); - data->dev = xstrdup (dev); data->access_mode = (flags & O_ACCMODE); data->fd = fd; @@ -716,7 +726,17 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) { free (data->dev); if (data->fd != -1) - close (data->fd); + { + if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) + { + fsync (data->fd); +#ifdef __linux__ + if (data->is_disk) + ioctl (data->fd, BLKFLSBUF, 0); +#endif + } + close (data->fd); + } fd = open (map[disk->id].device, flags); if (fd >= 0) @@ -876,7 +896,6 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) { grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device); - close (fd); return grub_errno; } @@ -926,6 +945,27 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, return grub_errno; } +grub_err_t +grub_util_biosdisk_flush (struct grub_disk *disk) +{ + struct grub_util_biosdisk_data *data = disk->data; + + if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID) + return GRUB_ERR_NONE; + if (data->fd == -1) + { + data->fd = open_device (disk, 0, O_RDONLY); + if (data->fd < 0) + return grub_errno; + } + fsync (data->fd); +#ifdef __linux__ + if (data->is_disk) + ioctl (data->fd, BLKFLSBUF, 0); +#endif + return GRUB_ERR_NONE; +} + static void grub_util_biosdisk_close (struct grub_disk *disk) { @@ -933,7 +973,11 @@ grub_util_biosdisk_close (struct grub_disk *disk) free (data->dev); if (data->fd != -1) - close (data->fd); + { + if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) + grub_util_biosdisk_flush (disk); + close (data->fd); + } free (data); } diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index c8b95443b..44c40b010 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -415,6 +415,18 @@ grub_make_system_path_relative_to_its_root (const char *path) if (offset == 0) { free (buf); +#ifdef __linux__ + { + char *bind; + grub_free (grub_find_root_device_from_mountinfo (buf2, &bind)); + if (bind && bind[0] && bind[1]) + { + buf3 = bind; + goto parsedir; + } + grub_free (bind); + } +#endif free (buf2); #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) if (poolfs) @@ -437,6 +449,21 @@ grub_make_system_path_relative_to_its_root (const char *path) } free (buf); buf3 = xstrdup (buf2 + offset); + buf2[offset] = 0; +#ifdef __linux__ + { + char *bind; + grub_free (grub_find_root_device_from_mountinfo (buf2, &bind)); + if (bind && bind[0] && bind[1]) + { + char *temp = buf3; + buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3); + grub_free (temp); + } + grub_free (bind); + } +#endif + free (buf2); #ifdef __CYGWIN__ @@ -452,6 +479,7 @@ grub_make_system_path_relative_to_its_root (const char *path) } #endif + parsedir: /* Remove trailing slashes, return empty string if root directory. */ len = strlen (buf3); while (len > 0 && buf3[len - 1] == '/') diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index 85ba8536c..6e7ed0e57 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -73,7 +73,7 @@ grub_file_open (const char *name) goto fail; /* Get the file part of NAME. */ - file_name = grub_strchr (name, ')'); + file_name = (name[0] == '(') ? grub_strchr (name, ')') : NULL; if (file_name) file_name++; else diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 37ce8decd..1b4cdec66 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -597,23 +597,23 @@ grub_reverse (char *str) /* Divide N by D, return the quotient, and store the remainder in *R. */ grub_uint64_t -grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r) +grub_divmod64_full (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) { /* This algorithm is typically implemented by hardware. The idea is to get the highest bit in N, 64 times, by keeping - upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper + upper(N * 2^i) = (Q * D + M), where upper represents the high 64 bits in 128-bits space. */ unsigned bits = 64; - unsigned long long q = 0; - unsigned m = 0; + grub_uint64_t q = 0; + grub_uint64_t m = 0; /* Skip the slow computation if 32-bit arithmetic is possible. */ - if (n < 0xffffffff) + if (n < 0xffffffff && d < 0xffffffff) { if (r) - *r = ((grub_uint32_t) n) % d; + *r = ((grub_uint32_t) n) % (grub_uint32_t) d; - return ((grub_uint32_t) n) / d; + return ((grub_uint32_t) n) / (grub_uint32_t) d; } while (bits--) diff --git a/grub-core/lib/cmos_datetime.c b/grub-core/lib/cmos_datetime.c index 8db60b48c..73c5a03c0 100644 --- a/grub-core/lib/cmos_datetime.c +++ b/grub-core/lib/cmos_datetime.c @@ -19,6 +19,9 @@ #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); grub_err_t grub_get_datetime (struct grub_datetime *datetime) diff --git a/grub-core/lib/crc.c b/grub-core/lib/crc.c new file mode 100644 index 000000000..ffc3ef3b5 --- /dev/null +++ b/grub-core/lib/crc.c @@ -0,0 +1,75 @@ +/* crc.c - crc function */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +static grub_uint32_t crc32c_table [256]; + +static void +init_crc32c_table (void) +{ + auto grub_uint32_t reflect (grub_uint32_t ref, int len); + grub_uint32_t reflect (grub_uint32_t ref, int len) + { + grub_uint32_t result = 0; + int i; + + for (i = 1; i <= len; i++) + { + if (ref & 1) + result |= 1 << (len - i); + ref >>= 1; + } + + return result; + } + + grub_uint32_t polynomial = 0x1edc6f41; + int i, j; + + for(i = 0; i < 256; i++) + { + crc32c_table[i] = reflect(i, 8) << 24; + for (j = 0; j < 8; j++) + crc32c_table[i] = (crc32c_table[i] << 1) ^ + (crc32c_table[i] & (1 << 31) ? polynomial : 0); + crc32c_table[i] = reflect(crc32c_table[i], 32); + } +} + +grub_uint32_t +grub_getcrc32c (grub_uint32_t crc, const void *buf, int size) +{ + int i; + const grub_uint8_t *data = buf; + + if (! crc32c_table[1]) + init_crc32c_table (); + + crc^= 0xffffffff; + + for (i = 0; i < size; i++) + { + crc = (crc >> 8) ^ crc32c_table[(crc & 0xFF) ^ *data]; + data++; + } + + return crc ^ 0xffffffff; +} diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index f5768b8b5..ad1bfc4d3 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -21,6 +21,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); struct grub_crypto_hmac_handle { diff --git a/grub-core/lib/efi/datetime.c b/grub-core/lib/efi/datetime.c index 0a91c345a..0fd1b5fbd 100644 --- a/grub-core/lib/efi/datetime.c +++ b/grub-core/lib/efi/datetime.c @@ -22,6 +22,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); grub_err_t grub_get_datetime (struct grub_datetime *datetime) diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S index c3768f4eb..982415de4 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -130,7 +130,7 @@ VARIABLE(grub_relocator16_ss) .byte 0xb8 VARIABLE(grub_relocator16_sp) .word 0 - movw %ax, %ss + movzwl %ax, %esp /* movw imm32, %edx. */ .byte 0x66, 0xba diff --git a/grub-core/lib/i386/setjmp.S b/grub-core/lib/i386/setjmp.S index a2002ae3d..5b7aa158b 100644 --- a/grub-core/lib/i386/setjmp.S +++ b/grub-core/lib/i386/setjmp.S @@ -17,9 +17,12 @@ */ #include +#include .file "setjmp.S" +GRUB_MOD_LICENSE ("GPLv3+") + .text /* diff --git a/grub-core/lib/ieee1275/datetime.c b/grub-core/lib/ieee1275/datetime.c index 7e6f8d1f1..4105c639b 100644 --- a/grub-core/lib/ieee1275/datetime.c +++ b/grub-core/lib/ieee1275/datetime.c @@ -20,6 +20,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); static char *rtc = 0; diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index fb1a52bf8..659fa7061 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -116,7 +116,7 @@ static struct legacy_command legacy_commands[] = " 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."}, - {"find", "search -sf '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILENAME", + {"find", "search -f '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILENAME", "Search for the filename FILENAME in all of partitions and print the list of" " the devices which contain the file."}, /* FIXME: fstest unsupported. */ @@ -680,7 +680,10 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) int base = 10; brk = curarg; if (brk[0] == '0' && brk[1] == 'x') - base = 16; + { + base = 16; + brk += 2; + } else if (brk[0] == '0') base = 8; for (; *brk && brk < curarg + curarglen; brk++) diff --git a/grub-core/lib/mips/setjmp.S b/grub-core/lib/mips/setjmp.S index 8ab6222c4..8259c9d22 100644 --- a/grub-core/lib/mips/setjmp.S +++ b/grub-core/lib/mips/setjmp.S @@ -17,9 +17,12 @@ */ #include +#include .file "setjmp.S" +GRUB_MOD_LICENSE ("GPLv3+") + .text /* diff --git a/grub-core/lib/pbkdf2.c b/grub-core/lib/pbkdf2.c index 083446ab9..09b8c7360 100644 --- a/grub-core/lib/pbkdf2.c +++ b/grub-core/lib/pbkdf2.c @@ -21,6 +21,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv2+"); /* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is HMAC variant of digest supplied by MD. Inputs are the password P of length PLEN, diff --git a/grub-core/lib/powerpc/setjmp.S b/grub-core/lib/powerpc/setjmp.S index 25cbaa3e9..8c7540e3c 100644 --- a/grub-core/lib/powerpc/setjmp.S +++ b/grub-core/lib/powerpc/setjmp.S @@ -17,9 +17,12 @@ */ #include +#include .file "setjmp.S" +GRUB_MOD_LICENSE ("GPLv3+") + .text /* diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c index 940b9133b..6eb20b865 100644 --- a/grub-core/lib/relocator.c +++ b/grub-core/lib/relocator.c @@ -22,6 +22,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); struct grub_relocator { @@ -1416,11 +1419,17 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, break; } + grub_dprintf ("relocator", "relocators_size=%ld\n", + (unsigned long) rel->relocators_size); + if (chunk->src < chunk->target) rel->relocators_size += grub_relocator_backward_size; if (chunk->src > chunk->target) rel->relocators_size += grub_relocator_forward_size; + grub_dprintf ("relocator", "relocators_size=%ld\n", + (unsigned long) rel->relocators_size); + chunk->size = size; chunk->next = rel->chunks; rel->chunks = chunk; diff --git a/grub-core/lib/sparc64/setjmp.S b/grub-core/lib/sparc64/setjmp.S index 0e23ecfa1..5c2ec2cf3 100644 --- a/grub-core/lib/sparc64/setjmp.S +++ b/grub-core/lib/sparc64/setjmp.S @@ -17,9 +17,12 @@ */ #include +#include .file "setjmp.S" +GRUB_MOD_LICENSE ("GPLv3+") + .text /* diff --git a/grub-core/lib/x86_64/setjmp.S b/grub-core/lib/x86_64/setjmp.S index 621b09b93..b1f1b22cb 100644 --- a/grub-core/lib/x86_64/setjmp.S +++ b/grub-core/lib/x86_64/setjmp.S @@ -17,9 +17,12 @@ */ #include +#include .file "setjmp.S" +GRUB_MOD_LICENSE ("GPLv3+") + .text /* diff --git a/grub-core/loader/aout.c b/grub-core/loader/aout.c index 611960f92..69bf6e6ad 100644 --- a/grub-core/loader/aout.c +++ b/grub-core/loader/aout.c @@ -21,6 +21,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + int grub_aout_get_type (union grub_aout_header *header) { diff --git a/grub-core/loader/efi/appleloader.c b/grub-core/loader/efi/appleloader.c index dc42683a6..db57a573c 100644 --- a/grub-core/loader/efi/appleloader.c +++ b/grub-core/loader/efi/appleloader.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; static grub_efi_handle_t image_handle; @@ -67,165 +69,60 @@ struct piwg_full_device_path struct grub_efi_device_path end; }; -/* early 2006 Core Duo / Core Solo models */ -static struct piwg_full_device_path devpath_1 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffe00000, - .end_address = 0xfff9ffff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} +#define MAKE_PIWG_PATH(st, en) \ + { \ + .comp1 = \ + { \ + .header = { \ + .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, \ + .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, \ + .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} \ + }, \ + .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, \ + .start_address = st, \ + .end_address = en \ + }, \ + .comp2 = \ + { \ + .header = { \ + .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, \ + .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, \ + .length = {sizeof (struct grub_efi_piwg_device_path), 0} \ + }, \ + .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, \ + 0x01, 0xAE, 0xF2, 0xB7}} \ + }, \ + .end = \ + { \ + .type = GRUB_EFI_END_DEVICE_PATH_TYPE, \ + .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, \ + .length = {sizeof (struct grub_efi_device_path), 0} \ + } \ } -}; + +/* early 2006 Core Duo / Core Solo models */ +static struct piwg_full_device_path devpath_1 = MAKE_PIWG_PATH (0xffe00000, + 0xfff9ffff); /* mid-2006 Mac Pro (and probably other Core 2 models) */ -static struct piwg_full_device_path devpath_2 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffe00000, - .end_address = 0xfff7ffff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} - } -}; +static struct piwg_full_device_path devpath_2 = MAKE_PIWG_PATH (0xffe00000, + 0xfff7ffff); /* mid-2007 MBP ("Santa Rosa" based models) */ -static struct piwg_full_device_path devpath_3 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffe00000, - .end_address = 0xfff8ffff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} - } -}; +static struct piwg_full_device_path devpath_3 = MAKE_PIWG_PATH (0xffe00000, + 0xfff8ffff); /* early-2008 MBA */ -static struct piwg_full_device_path devpath_4 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffc00000, - .end_address = 0xfff8ffff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} - } -}; +static struct piwg_full_device_path devpath_4 = MAKE_PIWG_PATH (0xffc00000, + 0xfff8ffff); /* late-2008 MB/MBP (NVidia chipset) */ -static struct piwg_full_device_path devpath_5 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffcb4000, - .end_address = 0xffffbfff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} - } -}; +static struct piwg_full_device_path devpath_5 = MAKE_PIWG_PATH (0xffcb4000, + 0xffffbfff); + +/* mid-2010 MB/MBP (NVidia chipset) */ +static struct piwg_full_device_path devpath_6 = MAKE_PIWG_PATH (0xffcc4000, + 0xffffbfff); struct devdata { @@ -240,6 +137,7 @@ struct devdata devs[] = {"MBP", (grub_efi_device_path_t *) &devpath_3}, {"MBA", (grub_efi_device_path_t *) &devpath_4}, {"MB NV", (grub_efi_device_path_t *) &devpath_5}, + {"MB NV2", (grub_efi_device_path_t *) &devpath_6}, {NULL, NULL}, }; diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c index a095ad931..869b64ced 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c @@ -35,6 +35,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; static grub_efi_physical_address_t address; diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index ecd5bd5cd..6487dc3df 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -34,6 +34,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #include #ifdef GRUB_MACHINE_PCBIOS #include diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 0178e2fd4..f19f471ab 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -35,6 +35,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #ifdef GRUB_MACHINE_PCBIOS #include #endif @@ -547,6 +549,7 @@ grub_linux_boot (void) #ifdef GRUB_MACHINE_EFI { grub_efi_uintn_t efi_desc_size; + grub_size_t efi_mmap_target; grub_efi_uint32_t efi_desc_version; err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL, &efi_desc_size, &efi_desc_version); @@ -554,23 +557,24 @@ grub_linux_boot (void) return err; /* Note that no boot services are available from here. */ - + efi_mmap_target = real_mode_target + + ((grub_uint8_t *) efi_mmap_buf - (grub_uint8_t *) real_mode_mem); /* Pass EFI parameters. */ if (grub_le_to_cpu16 (params->version) >= 0x0206) { params->v0206.efi_mem_desc_size = efi_desc_size; params->v0206.efi_mem_desc_version = efi_desc_version; - params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) efi_mmap_buf; + params->v0206.efi_mmap = efi_mmap_target; params->v0206.efi_mmap_size = efi_mmap_size; #ifdef __x86_64__ - params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) efi_mmap_buf >> 32); + params->v0206.efi_mmap_hi = (efi_mmap_target >> 32); #endif } else if (grub_le_to_cpu16 (params->version) >= 0x0204) { params->v0204.efi_mem_desc_size = efi_desc_size; params->v0204.efi_mem_desc_version = efi_desc_version; - params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) efi_mmap_buf; + params->v0204.efi_mmap = efi_mmap_target; params->v0204.efi_mmap_size = efi_mmap_size; } } diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index cc01a356a..abd4ae96d 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -448,7 +448,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target) bufsize = grub_multiboot_get_mbi_size (); err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, - 0, 0xffffffff - bufsize, + 0x10000, 0x100000 - bufsize, bufsize, 4, GRUB_RELOCATOR_PREFERENCE_NONE); if (err) diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c index fd99c81d5..794316b34 100644 --- a/grub-core/loader/i386/pc/chainloader.c +++ b/grub-core/loader/i386/pc/chainloader.c @@ -38,6 +38,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; static int boot_drive; static void *boot_part_addr; diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index 96d00f927..c6e6b67d1 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -36,6 +36,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_LINUX_CL_OFFSET 0x9000 #define GRUB_LINUX_CL_END_OFFSET 0x90FF diff --git a/grub-core/loader/i386/pc/ntldr.c b/grub-core/loader/i386/pc/ntldr.c index 0c33a0680..4a08b54f2 100644 --- a/grub-core/loader/i386/pc/ntldr.c +++ b/grub-core/loader/i386/pc/ntldr.c @@ -33,6 +33,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; static struct grub_relocator *rel; static grub_uint32_t edx = 0xffffffff; diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 6ae2a9321..0bf7b1f8e 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* For frequencies. */ #include #include @@ -379,8 +381,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_align (relocator, &ch, - target_addr + linux_size + 0x10000, - (0xffffffff - size) + 1, + (target_addr & 0x1fffffff) + + linux_size + 0x10000, + (0x10000000 - size), size, 0x10000, GRUB_RELOCATOR_PREFERENCE_NONE); diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 4bfc2c191..d9e74b3c7 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -43,6 +43,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #ifdef GRUB_MACHINE_EFI #include #endif diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c index 0cf0eb825..12a3fa9f6 100644 --- a/grub-core/loader/powerpc/ieee1275/linux.c +++ b/grub-core/loader/powerpc/ieee1275/linux.c @@ -29,6 +29,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define ELF32_LOADMASK (0xc0000000UL) #define ELF64_LOADMASK (0xc000000000000000ULL) diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c index a262049a7..8ed61f8bf 100644 --- a/grub-core/loader/sparc64/ieee1275/linux.c +++ b/grub-core/loader/sparc64/ieee1275/linux.c @@ -29,6 +29,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; static int loaded; diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c index 73158fd10..a98d60c20 100644 --- a/grub-core/loader/xnu.c +++ b/grub-core/loader/xnu.c @@ -34,6 +34,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #if defined (__i386) && !defined (GRUB_MACHINE_EFI) #include #endif diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c index 1c1825490..07a71336b 100644 --- a/grub-core/mmap/mmap.c +++ b/grub-core/mmap/mmap.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE struct grub_mmap_region *grub_mmap_overlays = 0; diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index cefb1cb9b..837fcb960 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -33,6 +33,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_DEFAULT_HISTORY_SIZE 50 static int nested_level = 0; diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index e62482122..5844cb2f0 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include /* Time to delay after displaying an error message about a default/fallback entry failing to boot. */ @@ -345,18 +347,44 @@ static void menu_init (int entry, grub_menu_t menu, int nested) { struct grub_term_output *term; + int gfxmenu = 0; + + FOR_ACTIVE_TERM_OUTPUTS(term) + if (grub_strcmp (term->name, "gfxterm") == 0) + { + if (grub_env_get ("theme")) + { + if (!grub_gfxmenu_try_hook) + { + grub_dl_load ("gfxmenu"); + grub_print_error (); + } + if (grub_gfxmenu_try_hook) + { + grub_err_t err; + err = grub_gfxmenu_try_hook (entry, menu, nested); + if(!err) + { + gfxmenu = 1; + break; + } + } + else + grub_error (GRUB_ERR_BAD_MODULE, "no gfxmenu found"); + grub_print_error (); + grub_wait_after_message (); + } + grub_errno = GRUB_ERR_NONE; + grub_gfxterm_fullscreen (); + break; + } FOR_ACTIVE_TERM_OUTPUTS(term) { grub_err_t err; - if (grub_gfxmenu_try_hook && grub_strcmp (term->name, "gfxterm") == 0) - { - err = grub_gfxmenu_try_hook (entry, menu, nested); - if(!err) - continue; - grub_errno = GRUB_ERR_NONE; - } + if (grub_strcmp (term->name, "gfxterm") == 0 && gfxmenu) + break; err = grub_menu_try_text (term, entry, menu, nested); if(!err) diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c index 94f6e7f32..dc5ab528f 100644 --- a/grub-core/normal/menu_entry.c +++ b/grub-core/normal/menu_entry.c @@ -52,6 +52,8 @@ struct per_term_screen int x; /* The Y coordinate. */ int y; + /* Number of entries. */ + int num_entries; }; struct screen @@ -188,7 +190,7 @@ print_down (int flag, struct per_term_screen *term_screen) grub_term_gotoxy (term_screen->term, GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term_screen->term), GRUB_TERM_TOP_BORDER_Y - + grub_term_num_entries (term_screen->term)); + + term_screen->num_entries); if (flag) grub_putcode (GRUB_UNICODE_DOWNARROW, term_screen->term); @@ -209,13 +211,12 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen, struct line *linep; /* Check if scrolling is necessary. */ - if (term_screen->y < 0 || term_screen->y - >= grub_term_num_entries (term_screen->term)) + if (term_screen->y < 0 || term_screen->y >= term_screen->num_entries) { if (term_screen->y < 0) term_screen->y = 0; else - term_screen->y = grub_term_num_entries (term_screen->term) - 1; + term_screen->y = term_screen->num_entries - 1; region_start = 0; region_column = 0; @@ -251,7 +252,7 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen, for (column = 0; column <= linep->len - && y < grub_term_num_entries (term_screen->term); + && y < term_screen->num_entries; column += grub_term_entry_width (term_screen->term), y++) { if (y < 0) @@ -272,7 +273,7 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen, print_line (linep, column, 0, y, term_screen); } - if (y == grub_term_num_entries (term_screen->term)) + if (y == term_screen->num_entries) { if (column <= linep->len || i + 1 < screen->num_lines) down_flag = 1; @@ -282,11 +283,11 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen, i++; if (mode == ALL_LINES && i == screen->num_lines) - for (; y < grub_term_num_entries (term_screen->term); y++) + for (; y < term_screen->num_entries; y++) print_empty_line (y, term_screen); } - while (y < grub_term_num_entries (term_screen->term)); + while (y < term_screen->num_entries); /* Draw up and down arrows. */ if (up) @@ -1165,7 +1166,7 @@ run (struct screen *screen) { char *script; int errs_before; - grub_menu_t menu; + grub_menu_t menu = NULL; char *dummy[1] = { NULL }; auto char * editor_getsource (void); @@ -1185,7 +1186,7 @@ run (struct screen *screen) size = 0; for (i = 0; i < screen->num_lines; i++) { - grub_strcpy (source + size, screen->lines[i].buf); + grub_memcpy (source + size, screen->lines[i].buf, screen->lines[i].len); size += screen->lines[i].len; source[size++] = '\n'; } @@ -1290,7 +1291,8 @@ grub_menu_entry_run (grub_menu_entry_t entry) } /* Draw the screen. */ for (i = 0; i < screen->nterms; i++) - grub_menu_init_page (0, 1, screen->terms[i].term); + grub_menu_init_page (0, 1, &screen->terms[i].num_entries, + screen->terms[i].term); update_screen_all (screen, 0, 0, 1, 1, ALL_LINES); for (i = 0; i < screen->nterms; i++) grub_term_setcursor (screen->terms[i].term, 1); diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c index fc4a89196..93f0492bc 100644 --- a/grub-core/normal/menu_text.c +++ b/grub-core/normal/menu_text.c @@ -34,10 +34,19 @@ static grub_uint8_t grub_color_menu_highlight; struct menu_viewer_data { int first, offset; + /* The number of entries shown at a time. */ + int num_entries; grub_menu_t menu; struct grub_term_output *term; }; +static inline int +grub_term_cursor_x (struct grub_term_output *term) +{ + return (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term) + - GRUB_TERM_MARGIN - 1); +} + grub_ssize_t grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position, struct grub_term_output *term) @@ -53,30 +62,45 @@ grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position, return width; } -void -grub_print_message_indented (const char *msg, int margin_left, int margin_right, - struct grub_term_output *term) +static int +grub_print_message_indented_real (const char *msg, int margin_left, + int margin_right, + struct grub_term_output *term, int dry_run) { grub_uint32_t *unicode_msg; grub_uint32_t *last_position; int msg_len; + int ret = 0; msg_len = grub_utf8_to_ucs4_alloc (msg, &unicode_msg, &last_position); if (msg_len < 0) { - return; + return 0; } - grub_print_ucs4 (unicode_msg, last_position, margin_left, margin_right, term); + if (dry_run) + ret = grub_ucs4_count_lines (unicode_msg, last_position, margin_left, + margin_right, term); + else + grub_print_ucs4 (unicode_msg, last_position, margin_left, + margin_right, term); grub_free (unicode_msg); + + return ret; } +void +grub_print_message_indented (const char *msg, int margin_left, int margin_right, + struct grub_term_output *term) +{ + grub_print_message_indented_real (msg, margin_left, margin_right, term, 0); +} static void -draw_border (struct grub_term_output *term) +draw_border (struct grub_term_output *term, int num_entries) { unsigned i; @@ -88,7 +112,7 @@ draw_border (struct grub_term_output *term) grub_putcode (GRUB_UNICODE_HLINE, term); grub_putcode (GRUB_UNICODE_CORNER_UR, term); - for (i = 0; i < (unsigned) grub_term_num_entries (term); i++) + for (i = 0; i < (unsigned) num_entries; i++) { grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1); grub_putcode (GRUB_UNICODE_VLINE, term); @@ -99,7 +123,7 @@ draw_border (struct grub_term_output *term) } grub_term_gotoxy (term, GRUB_TERM_MARGIN, - GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term) + 1); + GRUB_TERM_TOP_BORDER_Y + num_entries + 1); grub_putcode (GRUB_UNICODE_CORNER_LL, term); for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++) grub_putcode (GRUB_UNICODE_HLINE, term); @@ -108,22 +132,27 @@ draw_border (struct grub_term_output *term) grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); grub_term_gotoxy (term, GRUB_TERM_MARGIN, - (GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term) + (GRUB_TERM_TOP_BORDER_Y + num_entries + GRUB_TERM_MARGIN + 1)); } -static void -print_message (int nested, int edit, struct grub_term_output *term) +static int +print_message (int nested, int edit, struct grub_term_output *term, int dry_run) { + int ret = 0; grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); if (edit) { - grub_putcode ('\n', term); - grub_print_message_indented (_("Minimum Emacs-like screen editing is \ + if(dry_run) + ret++; + else + grub_putcode ('\n', term); + ret += grub_print_message_indented_real (_("Minimum Emacs-like screen editing is \ supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \ command-line or ESC to discard edits and return to the GRUB menu."), - STANDARD_MARGIN, STANDARD_MARGIN, term); + STANDARD_MARGIN, STANDARD_MARGIN, + term, dry_run); } else { @@ -134,30 +163,34 @@ command-line or ESC to discard edits and return to the GRUB menu."), msg_translated = grub_xasprintf (msg, GRUB_UNICODE_UPARROW, GRUB_UNICODE_DOWNARROW); if (!msg_translated) - return; - grub_putcode ('\n', term); - grub_print_message_indented (msg_translated, STANDARD_MARGIN, - STANDARD_MARGIN, term); + return 0; + if(dry_run) + ret++; + else + grub_putcode ('\n', term); + ret += grub_print_message_indented_real (msg_translated, STANDARD_MARGIN, + STANDARD_MARGIN, term, dry_run); grub_free (msg_translated); if (nested) { - grub_print_message_indented + ret += grub_print_message_indented_real (_("Press enter to boot the selected OS, " "\'e\' to edit the commands before booting " "or \'c\' for a command-line. ESC to return previous menu.\n"), - STANDARD_MARGIN, STANDARD_MARGIN, term); + STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); } else { - grub_print_message_indented + ret += grub_print_message_indented_real (_("Press enter to boot the selected OS, " "\'e\' to edit the commands before booting " "or \'c\' for a command-line.\n"), - STANDARD_MARGIN, STANDARD_MARGIN, term); + STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); } } + return ret; } static void @@ -256,52 +289,56 @@ print_entry (int y, int highlight, grub_menu_entry_t entry, } static void -print_entries (grub_menu_t menu, int first, int offset, - struct grub_term_output *term) +print_entries (grub_menu_t menu, const struct menu_viewer_data *data) { grub_menu_entry_t e; int i; - grub_term_gotoxy (term, - GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term), + grub_term_gotoxy (data->term, + GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (data->term), GRUB_TERM_FIRST_ENTRY_Y); - if (first) - grub_putcode (GRUB_UNICODE_UPARROW, term); + if (data->first) + grub_putcode (GRUB_UNICODE_UPARROW, data->term); else - grub_putcode (' ', term); + grub_putcode (' ', data->term); - e = grub_menu_get_entry (menu, first); + e = grub_menu_get_entry (menu, data->first); - for (i = 0; i < grub_term_num_entries (term); i++) + for (i = 0; i < data->num_entries; i++) { - print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e, term); + print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, data->offset == i, + e, data->term); if (e) e = e->next; } - grub_term_gotoxy (term, GRUB_TERM_LEFT_BORDER_X - + grub_term_border_width (term), - GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term)); + grub_term_gotoxy (data->term, GRUB_TERM_LEFT_BORDER_X + + grub_term_border_width (data->term), + GRUB_TERM_TOP_BORDER_Y + data->num_entries); if (e) - grub_putcode (GRUB_UNICODE_DOWNARROW, term); + grub_putcode (GRUB_UNICODE_DOWNARROW, data->term); else - grub_putcode (' ', term); + grub_putcode (' ', data->term); - grub_term_gotoxy (term, grub_term_cursor_x (term), - GRUB_TERM_FIRST_ENTRY_Y + offset); + grub_term_gotoxy (data->term, grub_term_cursor_x (data->term), + GRUB_TERM_FIRST_ENTRY_Y + data->offset); } /* Initialize the screen. If NESTED is non-zero, assume that this menu is run from another menu or a command-line. If EDIT is non-zero, show a message for the menu entry editor. */ void -grub_menu_init_page (int nested, int edit, +grub_menu_init_page (int nested, int edit, int *num_entries, struct grub_term_output *term) { grub_uint8_t old_color_normal, old_color_highlight; + /* 3 lines for timeout message and bottom margin. 2 lines for the border. */ + *num_entries = grub_term_height (term) - GRUB_TERM_TOP_BORDER_Y + - (print_message (nested, edit, term, 1) + 3) - 2; + grub_term_getcolor (term, &old_color_normal, &old_color_highlight); /* By default, use the same colors for the menu. */ @@ -316,9 +353,9 @@ grub_menu_init_page (int nested, int edit, grub_normal_init_page (term); grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight); - draw_border (term); + draw_border (term, *num_entries); grub_term_setcolor (term, old_color_normal, old_color_highlight); - print_message (nested, edit, term); + print_message (nested, edit, term, 0); } static void @@ -359,10 +396,10 @@ menu_text_set_chosen_entry (int entry, void *dataptr) int complete_redraw = 0; data->offset = entry - data->first; - if (data->offset > grub_term_num_entries (data->term) - 1) + if (data->offset > data->num_entries - 1) { - data->first = entry - (grub_term_num_entries (data->term) - 1); - data->offset = grub_term_num_entries (data->term) - 1; + data->first = entry - (data->num_entries - 1); + data->offset = data->num_entries - 1; complete_redraw = 1; } if (data->offset < 0) @@ -372,7 +409,7 @@ menu_text_set_chosen_entry (int entry, void *dataptr) complete_redraw = 1; } if (complete_redraw) - print_entries (data->menu, data->first, data->offset, data->term); + print_entries (data->menu, data); else { print_entry (GRUB_TERM_FIRST_ENTRY_Y + oldoffset, 0, @@ -436,15 +473,17 @@ grub_menu_try_text (struct grub_term_output *term, data->offset = entry; data->first = 0; - if (data->offset > grub_term_num_entries (data->term) - 1) - { - data->first = data->offset - (grub_term_num_entries (data->term) - 1); - data->offset = grub_term_num_entries (data->term) - 1; - } grub_term_setcursor (data->term, 0); - grub_menu_init_page (nested, 0, data->term); - print_entries (menu, data->first, data->offset, data->term); + grub_menu_init_page (nested, 0, &data->num_entries, data->term); + + if (data->offset > data->num_entries - 1) + { + data->first = data->offset - (data->num_entries - 1); + data->offset = data->num_entries - 1; + } + + print_entries (menu, data); grub_term_refresh (data->term); grub_menu_register_viewer (instance); diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c index a1aa3d783..a8b9e6683 100644 --- a/grub-core/normal/term.c +++ b/grub-core/normal/term.c @@ -515,14 +515,16 @@ print_ucs4_terminal (const grub_uint32_t * str, const grub_uint32_t * last_position, int margin_left, int margin_right, struct grub_term_output *term, - struct term_state *state) + struct term_state *state, + int dry_run) { const grub_uint32_t *ptr; - grub_ssize_t startwidth = get_startwidth (term, margin_left); + grub_ssize_t startwidth = dry_run ? 0 : get_startwidth (term, margin_left); grub_ssize_t line_width = startwidth; grub_ssize_t lastspacewidth = 0; grub_ssize_t max_width = get_maxwidth (term, margin_left, margin_right); const grub_uint32_t *line_start = str, *last_space = str - 1; + int lines = 0; for (ptr = str; ptr < last_position; ptr++) { @@ -552,7 +554,7 @@ print_ucs4_terminal (const grub_uint32_t * str, if (line_width > max_width && last_space > line_start) ptr = last_space; else if (line_width > max_width - && line_start == str && startwidth != 0) + && line_start == str && line_width - lastspacewidth < max_width - 5) { ptr = str; lastspacewidth = startwidth; @@ -560,50 +562,59 @@ print_ucs4_terminal (const grub_uint32_t * str, else lastspacewidth = line_width - last_width; - for (ptr2 = line_start; ptr2 < ptr; ptr2++) - { - /* Skip combining characters on non-UTF8 terminals. */ - if ((term->flags & GRUB_TERM_CODE_TYPE_MASK) - != GRUB_TERM_CODE_TYPE_UTF8_LOGICAL - && grub_unicode_get_comb_type (*ptr2) - != GRUB_UNICODE_COMB_NONE) - continue; - putcode_real (*ptr2, term); - } + lines++; - grub_print_spaces (term, margin_right); - grub_putcode ('\n', term); - if (state && ++state->num_lines - >= (grub_ssize_t) grub_term_height (term) - 2) + if (!dry_run) { - state->backlog_ucs4 = (ptr == last_space || *ptr == '\n') - ? ptr + 1 : ptr; - state->backlog_len = last_position - state->backlog_ucs4; - return 1; + for (ptr2 = line_start; ptr2 < ptr; ptr2++) + { + /* Skip combining characters on non-UTF8 terminals. */ + if ((term->flags & GRUB_TERM_CODE_TYPE_MASK) + != GRUB_TERM_CODE_TYPE_UTF8_LOGICAL + && grub_unicode_get_comb_type (*ptr2) + != GRUB_UNICODE_COMB_NONE) + continue; + putcode_real (*ptr2, term); + } + + grub_print_spaces (term, margin_right); + grub_putcode ('\n', term); + if (state && ++state->num_lines + >= (grub_ssize_t) grub_term_height (term) - 2) + { + state->backlog_ucs4 = (ptr == last_space || *ptr == '\n') + ? ptr + 1 : ptr; + state->backlog_len = last_position - state->backlog_ucs4; + return 1; + } } line_width -= lastspacewidth; - grub_print_spaces (term, margin_left); + if (!dry_run) + grub_print_spaces (term, margin_left); if (ptr == last_space || *ptr == '\n') ptr++; line_start = ptr; } } - { - const grub_uint32_t *ptr2; - for (ptr2 = line_start; ptr2 < last_position; ptr2++) - { - /* Skip combining characters on non-UTF8 terminals. */ - if ((term->flags & GRUB_TERM_CODE_TYPE_MASK) - != GRUB_TERM_CODE_TYPE_UTF8_LOGICAL - && grub_unicode_get_comb_type (*ptr2) - != GRUB_UNICODE_COMB_NONE) - continue; - putcode_real (*ptr2, term); - } - } - return 0; + if (line_start < last_position) + lines++; + if (!dry_run) + { + const grub_uint32_t *ptr2; + for (ptr2 = line_start; ptr2 < last_position; ptr2++) + { + /* Skip combining characters on non-UTF8 terminals. */ + if ((term->flags & GRUB_TERM_CODE_TYPE_MASK) + != GRUB_TERM_CODE_TYPE_UTF8_LOGICAL + && grub_unicode_get_comb_type (*ptr2) + != GRUB_UNICODE_COMB_NONE) + continue; + putcode_real (*ptr2, term); + } + } + return dry_run ? lines : 0; } static struct term_state * @@ -672,7 +683,7 @@ print_backlog (struct grub_term_output *term, int ret; ret = print_ucs4_terminal (state->backlog_ucs4, state->backlog_ucs4 + state->backlog_len, - margin_left, margin_right, term, state); + margin_left, margin_right, term, state, 0); if (!ret) { grub_free (state->free); @@ -706,15 +717,19 @@ static int print_ucs4_real (const grub_uint32_t * str, const grub_uint32_t * last_position, int margin_left, int margin_right, - struct grub_term_output *term, int backlog) + struct grub_term_output *term, int backlog, + int dry_run) { struct term_state *state = NULL; - if (backlog) - state = find_term_state (term); + if (!dry_run) + { + if (backlog) + state = find_term_state (term); - if (((term->getxy (term) >> 8) & 0xff) < margin_left) - grub_print_spaces (term, margin_left - ((term->getxy (term) >> 8) & 0xff)); + if (((term->getxy (term) >> 8) & 0xff) < margin_left) + grub_print_spaces (term, margin_left - ((term->getxy (term) >> 8) & 0xff)); + } if ((term->flags & GRUB_TERM_CODE_TYPE_MASK) == GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS @@ -743,16 +758,30 @@ print_ucs4_real (const grub_uint32_t * str, grub_print_error (); return 0; } - ret = put_glyphs_terminal (visual, visual_len, margin_left, margin_right, - term, state); - if (!ret) - grub_free (visual); + if (dry_run) + { + struct grub_unicode_glyph *vptr; + ret = 0; + for (vptr = visual; vptr < visual + visual_len; vptr++) + if (vptr->base == '\n') + ret++; + if (visual_len && visual[visual_len - 1].base != '\n') + ret++; + grub_free (visual); + } else - state->free = visual; + { + ret = put_glyphs_terminal (visual, visual_len, margin_left, + margin_right, term, state); + if (!ret) + grub_free (visual); + else + state->free = visual; + } return ret; } return print_ucs4_terminal (str, last_position, margin_left, margin_right, - term, state); + term, state, dry_run); } void @@ -762,9 +791,18 @@ grub_print_ucs4 (const grub_uint32_t * str, struct grub_term_output *term) { print_ucs4_real (str, last_position, margin_left, margin_right, - term, 0); + term, 0, 0); } +int +grub_ucs4_count_lines (const grub_uint32_t * str, + const grub_uint32_t * last_position, + int margin_left, int margin_right, + struct grub_term_output *term) +{ + return print_ucs4_real (str, last_position, margin_left, margin_right, + term, 0, 1); +} void grub_xputs_normal (const char *str) @@ -813,7 +851,7 @@ grub_xputs_normal (const char *str) { int cur; cur = print_ucs4_real (unicode_str, unicode_last_position, 0, 0, - term, grub_more); + term, grub_more, 0); if (cur) backlog = 1; } diff --git a/grub-core/partmap/acorn.c b/grub-core/partmap/acorn.c index 677ec61d5..9a68ddd92 100644 --- a/grub-core/partmap/acorn.c +++ b/grub-core/partmap/acorn.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define LINUX_NATIVE_MAGIC grub_cpu_to_le32 (0xdeafa1de) #define LINUX_SWAP_MAGIC grub_cpu_to_le32 (0xdeafab1e) #define LINUX_MAP_ENTRIES (512 / 12) diff --git a/grub-core/partmap/amiga.c b/grub-core/partmap/amiga.c index 1e0f23402..36e318beb 100644 --- a/grub-core/partmap/amiga.c +++ b/grub-core/partmap/amiga.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_amiga_rdsk { /* "RDSK". */ @@ -112,8 +114,9 @@ amiga_partition_map_iterate (grub_disk_t disk, return grub_errno; if (grub_memcmp (apart.magic, GRUB_AMIGA_PART_MAGIC, - sizeof (apart.magic)) == 0) - + sizeof (apart.magic)) != 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, + "invalid Amiga partition map"); /* Calculate the first block and the size of the partition. */ part.start = (grub_be_to_cpu32 (apart.lowcyl) * grub_be_to_cpu32 (apart.heads) diff --git a/grub-core/partmap/apple.c b/grub-core/partmap/apple.c index e162d18d7..c08cae589 100644 --- a/grub-core/partmap/apple.c +++ b/grub-core/partmap/apple.c @@ -22,6 +22,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_APPLE_HEADER_MAGIC 0x4552 #define GRUB_APPLE_PART_MAGIC 0x504D diff --git a/grub-core/partmap/bsdlabel.c b/grub-core/partmap/bsdlabel.c index 4dec3851c..888100aa2 100644 --- a/grub-core/partmap/bsdlabel.c +++ b/grub-core/partmap/bsdlabel.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #ifdef GRUB_UTIL #include #endif diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c index 7f2c36143..73a1c3b19 100644 --- a/grub-core/partmap/gpt.c +++ b/grub-core/partmap/gpt.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_uint8_t grub_gpt_magic[8] = { 0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54 diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index 31a0a0707..1b71c69ab 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static struct grub_partition_map grub_msdos_partition_map; diff --git a/grub-core/partmap/sun.c b/grub-core/partmap/sun.c index 7af95c939..c7ef681c4 100644 --- a/grub-core/partmap/sun.c +++ b/grub-core/partmap/sun.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_PARTMAP_SUN_MAGIC 0xDABE #define GRUB_PARTMAP_SUN_MAX_PARTS 8 #define GRUB_PARTMAP_SUN_WHOLE_DISK_ID 0x05 diff --git a/grub-core/partmap/sunpc.c b/grub-core/partmap/sunpc.c index ea69c28b9..28dc4f5be 100644 --- a/grub-core/partmap/sunpc.c +++ b/grub-core/partmap/sunpc.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define GRUB_PARTMAP_SUN_PC_MAGIC 0xDABE #define GRUB_PARTMAP_SUN_PC_MAX_PARTS 16 #define GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID 0x05 diff --git a/grub-core/parttool/msdospart.c b/grub-core/parttool/msdospart.c index 006a87def..ecaca140a 100644 --- a/grub-core/parttool/msdospart.c +++ b/grub-core/parttool/msdospart.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv2+"); + static int activate_table_handle = -1; static int type_table_handle = -1; diff --git a/grub-core/script/lexer.c b/grub-core/script/lexer.c index 909b515fa..98279079f 100644 --- a/grub-core/script/lexer.c +++ b/grub-core/script/lexer.c @@ -126,7 +126,7 @@ int grub_script_lexer_yywrap (struct grub_parser_param *parserstate, const char *input) { - int len; + int len = 0; char *p = 0; char *line = 0; YY_BUFFER_STATE buffer; diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c index 7ce287ecc..210ac21cc 100644 --- a/grub-core/term/at_keyboard.c +++ b/grub-core/term/at_keyboard.c @@ -26,6 +26,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static short at_keyboard_status = 0; static int e0_received = 0; static int f0_received = 0; diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 44d1a9be8..e58d6722d 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -31,6 +31,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define DEFAULT_VIDEO_MODE "auto" #define DEFAULT_BORDER_WIDTH 10 @@ -343,7 +345,6 @@ grub_gfxterm_fullscreen (void) grub_video_swap_buffers (); grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height); } - bitmap = 0; /* Select the font to use. */ font_name = grub_env_get ("gfxterm_font"); @@ -392,12 +393,6 @@ grub_gfxterm_term_init (struct grub_term_output *term __attribute__ ((unused))) static void destroy_window (void) { - if (bitmap) - { - grub_video_bitmap_destroy (bitmap); - bitmap = 0; - } - repaint_callback = 0; grub_virtual_screen_free (); } diff --git a/grub-core/term/i386/pc/vga_text.c b/grub-core/term/i386/pc/vga_text.c index fbb65ae0c..1816bfae2 100644 --- a/grub-core/term/i386/pc/vga_text.c +++ b/grub-core/term/i386/pc/vga_text.c @@ -22,6 +22,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define COLS 80 #define ROWS 25 diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index 32628dbae..073c27aed 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define FOR_SERIAL_PORTS(var) FOR_LIST_ELEMENTS((var), (grub_serial_ports)) /* Argument options. */ diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c index 0a8c75c74..16158139d 100644 --- a/grub-core/term/terminfo.c +++ b/grub-core/term/terminfo.c @@ -34,6 +34,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static struct grub_term_output *terminfo_outputs; /* Get current terminfo name. */ diff --git a/grub-core/term/usb_keyboard.c b/grub-core/term/usb_keyboard.c index 23c0c10ca..ae00936b8 100644 --- a/grub-core/term/usb_keyboard.c +++ b/grub-core/term/usb_keyboard.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + enum diff --git a/grub-core/tests/example_functional_test.c b/grub-core/tests/example_functional_test.c index 525988145..802088791 100644 --- a/grub-core/tests/example_functional_test.c +++ b/grub-core/tests/example_functional_test.c @@ -18,6 +18,9 @@ /* All tests need to include test.h for GRUB testing framework. */ #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); /* Functional test main method. */ static void diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c index 521f4ad22..fd199bd63 100644 --- a/grub-core/tests/lib/functional_test.c +++ b/grub-core/tests/lib/functional_test.c @@ -20,6 +20,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); static grub_err_t grub_functional_test (grub_extcmd_context_t ctxt __attribute__ ((unused)), diff --git a/grub-core/tests/test_blockarg.c b/grub-core/tests/test_blockarg.c index 41460fb7e..ddd46e1f6 100644 --- a/grub-core/tests/test_blockarg.c +++ b/grub-core/tests/test_blockarg.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t test_blockarg (grub_extcmd_context_t ctxt, int argc, char **args) { diff --git a/grub-core/video/bitmap.c b/grub-core/video/bitmap.c index 659ab9a57..32e9358a3 100644 --- a/grub-core/video/bitmap.c +++ b/grub-core/video/bitmap.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* List of bitmap readers registered to system. */ static grub_video_bitmap_reader_t bitmap_readers_list; diff --git a/grub-core/video/bitmap_scale.c b/grub-core/video/bitmap_scale.c index 6f8ff247e..8da5697f8 100644 --- a/grub-core/video/bitmap_scale.c +++ b/grub-core/video/bitmap_scale.c @@ -23,6 +23,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); /* Prototypes for module-local functions. */ static grub_err_t scale_nn (struct grub_video_bitmap *dst, diff --git a/grub-core/video/bochs.c b/grub-core/video/bochs.c index 832cd9903..79cae6547 100644 --- a/grub-core/video/bochs.c +++ b/grub-core/video/bochs.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static struct { struct grub_video_mode_info mode_info; diff --git a/grub-core/video/cirrus.c b/grub-core/video/cirrus.c index a964c85cd..7fad50e5b 100644 --- a/grub-core/video/cirrus.c +++ b/grub-core/video/cirrus.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static struct { struct grub_video_mode_info mode_info; diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c index f02dc9cb6..d14ae98d2 100644 --- a/grub-core/video/efi_gop.c +++ b/grub-core/video/efi_gop.c @@ -29,6 +29,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_efi_guid_t graphics_output_guid = GRUB_EFI_GOP_GUID; static struct grub_efi_gop *gop; static unsigned old_mode; diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c index a8f70edea..1e709a52d 100644 --- a/grub-core/video/efi_uga.c +++ b/grub-core/video/efi_uga.c @@ -30,6 +30,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID; static struct grub_efi_uga_draw_protocol *uga; static grub_uint32_t uga_fb; diff --git a/grub-core/video/emu/sdl.c b/grub-core/video/emu/sdl.c index d66b8b0c0..f4c1a6ab6 100644 --- a/grub-core/video/emu/sdl.c +++ b/grub-core/video/emu/sdl.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static SDL_Surface *window = 0; static struct grub_video_render_target *sdl_render_target; static struct grub_video_mode_info mode_info; diff --git a/grub-core/video/fb/video_fb.c b/grub-core/video/fb/video_fb.c index 768b63328..2cffcb3d9 100644 --- a/grub-core/video/fb/video_fb.c +++ b/grub-core/video/fb/video_fb.c @@ -24,6 +24,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); static struct { @@ -1445,13 +1448,16 @@ grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask, GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, 0)) { + /* It was much nicer with the cast directly at function call but + some older gcc versions don't accept it properly.*/ + void *tmp = (void *) page0_ptr; mode_info->mode_type |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target, &framebuffer.back_target, *mode_info, - (void *) page0_ptr); + tmp); if (!err) { diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 08bf124b6..a109bcf43 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -30,6 +30,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static int vbe_detected = -1; static struct grub_vbe_info_block controller_info; diff --git a/grub-core/video/i386/pc/vga.c b/grub-core/video/i386/pc/vga.c index 19770ce0a..fe387a26b 100644 --- a/grub-core/video/i386/pc/vga.c +++ b/grub-core/video/i386/pc/vga.c @@ -30,6 +30,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define VGA_WIDTH 640 #define VGA_HEIGHT 350 #define VGA_MEM ((grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR) diff --git a/grub-core/video/ieee1275.c b/grub-core/video/ieee1275.c index 501ba7c2f..913ea8376 100644 --- a/grub-core/video/ieee1275.c +++ b/grub-core/video/ieee1275.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* Only 8-bit indexed color is supported for now. */ static unsigned old_width, old_height; diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c index 9d88163bd..8cdb2f61d 100644 --- a/grub-core/video/readers/jpeg.c +++ b/grub-core/video/readers/jpeg.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* Uncomment following define to enable JPEG debug. */ //#define JPEG_DEBUG diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c index 2cec49e2f..5728651e0 100644 --- a/grub-core/video/readers/png.c +++ b/grub-core/video/readers/png.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* Uncomment following define to enable PNG debug. */ //#define PNG_DEBUG diff --git a/grub-core/video/readers/tga.c b/grub-core/video/readers/tga.c index 6c9e9d691..84be68a0a 100644 --- a/grub-core/video/readers/tga.c +++ b/grub-core/video/readers/tga.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* Uncomment following define to enable TGA debug. */ //#define TGA_DEBUG diff --git a/grub-core/video/video.c b/grub-core/video/video.c index 7a1a446e4..6a1d47304 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -22,6 +22,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* The list of video adapters registered to system. */ grub_video_adapter_t grub_video_adapter_list = NULL; diff --git a/include/grub/deflate.h b/include/grub/deflate.h new file mode 100644 index 000000000..6ec4eaa99 --- /dev/null +++ b/include/grub/deflate.h @@ -0,0 +1,26 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_DEFLATE_HEADER +#define GRUB_DEFLATE_HEADER 1 + +grub_ssize_t +grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off, + char *outbuf, grub_size_t outsize); + +#endif diff --git a/include/grub/dl.h b/include/grub/dl.h index afc4af41a..6f23f7d63 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -21,15 +21,18 @@ #define GRUB_DL_H 1 #include +#ifndef ASM_FILE #include #include #include +#endif /* * Macros GRUB_MOD_INIT and GRUB_MOD_FINI are also used by build rules * to collect module names, so we define them only when they are not * defined already. */ +#ifndef ASM_FILE #ifndef GRUB_MOD_INIT #define GRUB_MOD_INIT(name) \ @@ -63,8 +66,52 @@ __asm__ (".section .modname\n.asciz \"" #name "\"\n") #define GRUB_MOD_DEP(name) \ __asm__ (".section .moddeps\n.asciz \"" #name "\"\n") + #endif +#endif + +#ifndef ASM_FILE +#ifdef APPLE_CC +#define GRUB_MOD_SECTION(x) "_" #x ", _" #x "" +#else +#define GRUB_MOD_SECTION(x) "." #x +#endif +#else +#ifdef APPLE_CC +#define GRUB_MOD_SECTION(x) _ ## x , _ ##x +#else +#define GRUB_MOD_SECTION(x) . ## x +#endif +#endif + +/* Me, Vladimir Serbinenko, hereby I add this module check as per new + GNU module policy. Note that this license check is informative only. + Modules have to be licensed under GPLv3 or GPLv3+ (optionally + multi-licensed under other licences as well) independently of the + presence of this check and solely by linking (module loading in GRUB + constitutes linking) and GRUB core being licensed under GPLv3+. + Be sure to understand your license obligations. +*/ +#ifndef ASM_FILE +#define GRUB_MOD_LICENSE(license) \ + static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), used)) = "LICENSE=" license; +#else +#define GRUB_MOD_LICENSE(license) \ + .section GRUB_MOD_SECTION(module_license), "a"; \ + .ascii "LICENSE="; \ + .ascii license; \ + .byte 0 +#endif + +/* Under GPL license obligations you have to distribute your module + under GPLv3(+). However, you can also distribute the same code under + another license as long as GPLv3(+) version is provided. +*/ +#define GRUB_MOD_DUAL_LICENSE(x) + +#ifndef ASM_FILE + struct grub_dl_segment { struct grub_dl_segment *next; @@ -119,4 +166,6 @@ grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr); void grub_arch_dl_init_linker (void); #endif +#endif + #endif /* ! GRUB_DL_H */ diff --git a/include/grub/efiemu/efiemu.h b/include/grub/efiemu/efiemu.h index 8eee98b61..9cedc3226 100644 --- a/include/grub/efiemu/efiemu.h +++ b/include/grub/efiemu/efiemu.h @@ -21,6 +21,7 @@ #include #include +#include #define GRUB_EFIEMU_PAGESIZE 4096 @@ -227,9 +228,7 @@ grub_efiemu_finish_boot_services (grub_efi_uintn_t *memory_map_size, grub_efi_uint32_t *descriptor_version); grub_err_t -grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)); +grub_efiemu_mmap_iterate (grub_memory_hook_t hook); int grub_efiemu_sizeof_uintn_t (void); grub_err_t grub_efiemu_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper); diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index d8cc02e14..842dff496 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -28,5 +28,6 @@ char *grub_util_biosdisk_get_grub_dev (const char *os_dev); const char *grub_util_biosdisk_get_osdev (grub_disk_t disk); int grub_util_biosdisk_is_present (const char *name); int grub_util_biosdisk_is_floppy (grub_disk_t disk); +grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index ef0d18300..d4ebcb0d1 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -78,4 +78,6 @@ extern char * canonicalize_file_name (const char *path); int grub_device_mapper_supported (void); #endif +char *grub_find_root_device_from_mountinfo (const char *dir, char **relroot); + #endif /* GRUB_EMU_MISC_H */ diff --git a/include/grub/err.h b/include/grub/err.h index 211fafa70..40f39dd5d 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -59,7 +59,8 @@ typedef enum GRUB_ERR_NET_BAD_ADDRESS, GRUB_ERR_NET_ROUTE_LOOP, GRUB_ERR_NET_NO_ROUTE, - GRUB_ERR_WAIT + GRUB_ERR_WAIT, + GRUB_ERR_BUG } grub_err_t; diff --git a/include/grub/fs.h b/include/grub/fs.h index 994eb8080..2c39332a9 100644 --- a/include/grub/fs.h +++ b/include/grub/fs.h @@ -31,9 +31,9 @@ struct grub_file; struct grub_dirhook_info { - int dir:1; - int mtimeset:1; - int case_insensitive:1; + unsigned dir:1; + unsigned mtimeset:1; + unsigned case_insensitive:1; grub_int32_t mtime; }; diff --git a/include/grub/gfxwidgets.h b/include/grub/gfxwidgets.h index f9678bf9e..8ce666c5c 100644 --- a/include/grub/gfxwidgets.h +++ b/include/grub/gfxwidgets.h @@ -36,6 +36,7 @@ struct grub_gfxmenu_box void (*draw) (grub_gfxmenu_box_t self, int x, int y); void (*set_content_size) (grub_gfxmenu_box_t self, int width, int height); + int (*get_border_width) (grub_gfxmenu_box_t self); int (*get_left_pad) (grub_gfxmenu_box_t self); int (*get_top_pad) (grub_gfxmenu_box_t self); int (*get_right_pad) (grub_gfxmenu_box_t self); diff --git a/include/grub/lib/crc.h b/include/grub/lib/crc.h new file mode 100644 index 000000000..c5098a8c3 --- /dev/null +++ b/include/grub/lib/crc.h @@ -0,0 +1,25 @@ +/* crc.h - prototypes for crc */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_CRC_H +#define GRUB_CRC_H 1 + +grub_uint32_t grub_getcrc32c (grub_uint32_t crc, const void *buf, int size); + +#endif /* ! GRUB_CRC_H */ diff --git a/include/grub/lvm.h b/include/grub/lvm.h index 220517183..b962dfd6c 100644 --- a/include/grub/lvm.h +++ b/include/grub/lvm.h @@ -60,21 +60,16 @@ struct grub_lvm_segment { unsigned int extent_count; enum { GRUB_LVM_STRIPED, GRUB_LVM_MIRROR } type; - unsigned int mirror_count; - struct grub_lvm_mirror *mirrors; + unsigned int node_count; + struct grub_lvm_node *nodes; - unsigned int stripe_count; unsigned int stripe_size; - struct grub_lvm_stripe *stripes; /* Pointer to stripe_count stripes. */ }; -struct grub_lvm_stripe { - int start; +struct grub_lvm_node { + grub_disk_addr_t start; + char *name; struct grub_lvm_pv *pv; -}; - -struct grub_lvm_mirror { - char *lvname; struct grub_lvm_lv *lv; }; diff --git a/include/grub/misc.h b/include/grub/misc.h index 6fcaa148b..80588be33 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -287,8 +287,20 @@ char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...) char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) __attribute__ ((warn_unused_result)); void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn)); -grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, - grub_uint32_t d, grub_uint32_t *r); +grub_uint64_t EXPORT_FUNC(grub_divmod64_full) (grub_uint64_t n, + grub_uint64_t d, + grub_uint64_t *r); +static inline grub_uint64_t grub_divmod64 (grub_uint64_t n, + grub_uint32_t d, + grub_uint32_t *r) +{ + grub_uint64_t ret, rr; + + ret = grub_divmod64_full (n, d, &rr); + if (r) + *r = rr; + return ret; +} #if NEED_ENABLE_EXECUTE_STACK && !defined(GRUB_UTIL) void EXPORT_FUNC(__enable_execute_stack) (void *addr); diff --git a/include/grub/normal.h b/include/grub/normal.h index 3b99e073a..08c14d209 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -51,7 +51,7 @@ extern int grub_normal_exit_level; /* Defined in `main.c'. */ void grub_enter_normal_mode (const char *config); void grub_normal_execute (const char *config, int nested, int batch); -void grub_menu_init_page (int nested, int edit, +void grub_menu_init_page (int nested, int edit, int *num_entries, struct grub_term_output *term); void grub_normal_init_page (struct grub_term_output *term); char *grub_file_getline (grub_file_t file); @@ -80,6 +80,11 @@ grub_print_ucs4 (const grub_uint32_t * str, const grub_uint32_t * last_position, int margin_left, int margin_right, struct grub_term_output *term); +int +grub_ucs4_count_lines (const grub_uint32_t * str, + const grub_uint32_t * last_position, + int margin_left, int margin_right, + struct grub_term_output *term); grub_ssize_t grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position, struct grub_term_output *term); diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 817372b69..31deb5031 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -38,9 +38,9 @@ #define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x1c /* The size of the first region which won't be compressed. */ -#define GRUB_KERNEL_I386_PC_RAW_SIZE 0xca4 +#define GRUB_KERNEL_I386_PC_RAW_SIZE 0xcd0 -#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x70c +#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x730 /* The offset of GRUB_PREFIX. */ #define GRUB_KERNEL_I386_PC_PREFIX GRUB_KERNEL_I386_PC_RAW_SIZE diff --git a/include/grub/term.h b/include/grub/term.h index dbcb2f52c..726c84dbf 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -140,9 +140,6 @@ grub_term_color_state; /* The X position of the left border. */ #define GRUB_TERM_LEFT_BORDER_X GRUB_TERM_MARGIN -/* The number of lines of messages at the bottom. */ -#define GRUB_TERM_MESSAGE_HEIGHT 8 - /* The Y position of the first entry. */ #define GRUB_TERM_FIRST_ENTRY_Y (GRUB_TERM_TOP_BORDER_Y + 1) @@ -339,29 +336,6 @@ grub_term_entry_width (struct grub_term_output *term) return grub_term_border_width (term) - 2 - GRUB_TERM_MARGIN * 2 - 1; } -/* The height of the border. */ - -static inline unsigned -grub_term_border_height (struct grub_term_output *term) -{ - return grub_term_height (term) - GRUB_TERM_TOP_BORDER_Y - - GRUB_TERM_MESSAGE_HEIGHT; -} - -/* The number of entries shown at a time. */ -static inline int -grub_term_num_entries (struct grub_term_output *term) -{ - return grub_term_border_height (term) - 2; -} - -static inline int -grub_term_cursor_x (struct grub_term_output *term) -{ - return (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term) - - GRUB_TERM_MARGIN - 1); -} - static inline grub_uint16_t grub_term_getxy (struct grub_term_output *term) { diff --git a/include/grub/util/raid.h b/include/grub/util/raid.h index 67020bb86..4da5eaaa8 100644 --- a/include/grub/util/raid.h +++ b/include/grub/util/raid.h @@ -21,7 +21,7 @@ #define GRUB_RAID_UTIL_HEADER 1 #ifdef __linux__ -char** grub_util_raid_getmembers (char *name); +char** grub_util_raid_getmembers (const char *name); #endif #endif /* ! GRUB_RAID_UTIL_HEADER */ diff --git a/po/README b/po/README index 801599583..5541f4229 100644 --- a/po/README +++ b/po/README @@ -8,6 +8,10 @@ that will hopefully clarify the situation. rsync -Lrtvz translationproject.org::tp/latest/grub/ po + Then create a po/LINGUAS file listing all the language codes: + + (cd po && ls *.po | cut -d. -f1 | xargs) >po/LINGUAS + GRUB's build system will automatically detect those and include them in your install. diff --git a/tests/partmap_test.in b/tests/partmap_test.in index 5a9c1a93d..7e9cef7c6 100644 --- a/tests/partmap_test.in +++ b/tests/partmap_test.in @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -parted=/sbin/parted +parted=parted grubshell=@builddir@/grub-shell create_disk_image () { diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 2fcde4ab0..293bdf74a 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -111,7 +111,8 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) file = grub_file_open (pathname); if (!file) { - grub_util_error (_("cannot open file %s"), pathname); + grub_util_error (_("cannot open file %s:%s"), pathname, + grub_errmsg); return; } @@ -221,6 +222,14 @@ cmd_cmp (char *src, char *dest) grub_util_error (_("seek error")); read_file (src, cmp_hook); + + { + grub_uint64_t pre; + pre = ftell (ff); + fseek (ff, 0, SEEK_END); + if (pre != ftell (ff)) + grub_util_error (_("unexpected end of file")); + } fclose (ff); } diff --git a/util/grub-install.in b/util/grub-install.in index 4e78dfadb..ff8bea87c 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -467,7 +467,8 @@ fi fs_module="`"$grub_probe" --device-map="${device_map}" --target=fs --device "${grub_device}"`" if test "x$fs_module" = x ; then echo "Auto-detection of a filesystem of ${grub_device} failed." 1>&2 - echo "Please report this together with the output of \"$grub_probe --device-map=\"${device_map}\" --target=fs -v ${grubdir}\" to " 1>&2 + echo "Try with --recheck." 1>&2 + echo "If the problem persists please report this together with the output of \"$grub_probe --device-map=\"${device_map}\" --target=fs -v ${grubdir}\" to " 1>&2 exit 1 fi diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index b041a38d7..afc66f886 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -280,6 +280,8 @@ for i in ${grub_mkconfig_dir}/* ; do case "$i" in # emacsen backup files. FIXME: support other editors *~) ;; + # emacsen autosave files. FIXME: support other editors + \#*\#) ;; *) if grub_file_is_not_garbage "$i" && test -x "$i" ; then echo diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 628ea34d4..2c5fd8c6f 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -16,19 +16,19 @@ transform="@program_transform_name@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -datarootdir=@datarootdir@ -datadir=@datadir@ -bindir=@bindir@ -sbindir=@sbindir@ -pkgdatadir=${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"` +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +datadir="@datadir@" +bindir="@bindir@" +sbindir="@sbindir@" +pkgdatadir="${datadir}/`echo "@PACKAGE_TARNAME@" | sed "${transform}"`" if test "x$grub_probe" = x; then - grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` + grub_probe="${sbindir}/`echo grub-probe | sed "${transform}"`" fi if test "x$grub_mkrelpath" = x; then - grub_mkrelpath=${bindir}/`echo grub-mkrelpath | sed ${transform}` + grub_mkrelpath="${bindir}/`echo grub-mkrelpath | sed "${transform}"`" fi if $(which gettext >/dev/null 2>/dev/null) ; then @@ -44,20 +44,20 @@ grub_warn () make_system_path_relative_to_its_root () { - ${grub_mkrelpath} $1 + "${grub_mkrelpath}" "$1" } is_path_readable_by_grub () { - path=$1 + path="$1" # abort if path doesn't exist - if test -e $path ; then : ;else + if test -e "$path" ; then : ;else return 1 fi # abort if file is in a filesystem we can't read - if ${grub_probe} -t fs $path > /dev/null 2>&1 ; then : ; else + if "${grub_probe}" -t fs "$path" > /dev/null 2>&1 ; then : ; else return 1 fi @@ -72,24 +72,24 @@ is_path_readable_by_grub () convert_system_path_to_grub_path () { - path=$1 + path="$1" grub_warn "convert_system_path_to_grub_path() is deprecated. Use prepare_grub_to_access_device() instead." # abort if GRUB can't access the path - if is_path_readable_by_grub ${path} ; then : ; else + if is_path_readable_by_grub "${path}" ; then : ; else return 1 fi - if drive=`${grub_probe} -t drive $path` ; then : ; else + if drive="`"${grub_probe}" -t drive "$path"`" ; then : ; else return 1 fi - if relative_path=`make_system_path_relative_to_its_root $path` ; then : ; else + if relative_path="`make_system_path_relative_to_its_root "$path"`" ; then : ; else return 1 fi - echo ${drive}${relative_path} + echo "${drive}${relative_path}" } save_default_entry () @@ -103,15 +103,15 @@ EOF prepare_grub_to_access_device () { - device=$1 + device="$1" # Abstraction modules aren't auto-loaded. - abstraction="`${grub_probe} --device ${device} --target=abstraction`" + abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`" for module in ${abstraction} ; do echo "insmod ${module}" done - partmap="`${grub_probe} --device ${device} --target=partmap`" + partmap="`"${grub_probe}" --device "${device}" --target=partmap`" for module in ${partmap} ; do case "${module}" in netbsd | openbsd) @@ -121,15 +121,15 @@ prepare_grub_to_access_device () esac done - fs="`${grub_probe} --device ${device} --target=fs`" + fs="`"${grub_probe}" --device "${device}" --target=fs`" for module in ${fs} ; do echo "insmod ${module}" done # If there's a filesystem UUID that GRUB is capable of identifying, use it; # otherwise set root as per value in device.map. - echo "set root='`${grub_probe} --device ${device} --target=drive`'" - if fs_uuid="`${grub_probe} --device ${device} --target=fs_uuid 2> /dev/null`" ; then + echo "set root='`"${grub_probe}" --device "${device}" --target=drive`'" + if fs_uuid="`"${grub_probe}" --device "${device}" --target=fs_uuid 2> /dev/null`" ; then echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}" fi } @@ -149,21 +149,21 @@ grub_file_is_not_garbage () version_test_numeric () { - local a=$1 - local cmp=$2 - local b=$3 + local a="$1" + local cmp="$2" + local b="$3" if [ "$a" = "$b" ] ; then - case $cmp in + case "$cmp" in ge|eq|le) return 0 ;; gt|lt) return 1 ;; esac fi if [ "$cmp" = "lt" ] ; then - c=$a - a=$b - b=$c + c="$a" + a="$b" + b="$c" fi - if (echo $a ; echo $b) | sort -n | head -n 1 | grep -qx $b ; then + if (echo "$a" ; echo "$b") | sort -n | head -n 1 | grep -qx "$b" ; then return 0 else return 1 @@ -172,25 +172,25 @@ version_test_numeric () version_test_gt () { - local a=`echo $1 | sed -e "s/[^-]*-//"` - local b=`echo $2 | sed -e "s/[^-]*-//"` + local a="`echo "$1" | sed -e "s/[^-]*-//"`" + local b="`echo "$2" | sed -e "s/[^-]*-//"`" local cmp=gt if [ "x$b" = "x" ] ; then return 0 fi - case $a:$b in + case "$a:$b" in *.old:*.old) ;; - *.old:*) a=`echo -n $a | sed -e s/\.old$//` ; cmp=gt ;; - *:*.old) b=`echo -n $b | sed -e s/\.old$//` ; cmp=ge ;; + *.old:*) a="`echo -n "$a" | sed -e 's/\.old$//'`" ; cmp=gt ;; + *:*.old) b="`echo -n "$b" | sed -e 's/\.old$//'`" ; cmp=ge ;; esac - version_test_numeric $a $cmp $b - return $? + version_test_numeric "$a" "$cmp" "$b" + return "$?" } version_find_latest () { local a="" - for i in $@ ; do + for i in "$@" ; do if version_test_gt "$i" "$a" ; then a="$i" fi @@ -202,7 +202,7 @@ version_find_latest () # printf; so this turns ' into \'. Note that you must use the output of # this function in a printf format string. gettext_quoted () { - $gettext "$@" | sed "s/'/'\\\\\\\\''/g" + "$gettext" "$@" | sed "s/'/'\\\\\\\\''/g" } # Run the first argument through gettext_quoted, and then pass that and all @@ -215,9 +215,9 @@ gettext_printf () { } uses_abstraction () { - device=$1 + device="$1" - abstraction="`${grub_probe} --device ${device} --target=abstraction`" + abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`" for module in ${abstraction}; do if test "x${module}" = "x$2"; then return 0 diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 876e9c9b2..2ba351596 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -1174,14 +1174,16 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], sha512sum utility after compiling on Gnewsense. */ const grub_uint8_t fwstart_good_hash[] = - { 0x75, 0xbf, 0xa3, 0x0e, 0x7c, 0xd1, 0x03, 0x82, - 0xe1, 0x34, 0x55, 0xd7, 0x09, 0x1e, 0x6c, 0xcc, - 0xef, 0x08, 0x61, 0xc1, 0x3c, 0xd8, 0xc7, 0x9f, - 0xe8, 0x2d, 0x3d, 0xb2, 0xda, 0x41, 0xd3, 0x83, - 0xd7, 0xb8, 0xe3, 0xd7, 0x13, 0xec, 0x9b, 0xf6, - 0xf6, 0xae, 0x6b, 0x32, 0x29, 0xc1, 0x69, 0x82, - 0xfa, 0x65, 0x2d, 0x97, 0x3e, 0x83, 0x6e, 0x6c, - 0xce, 0x34, 0x10, 0x59, 0x74, 0x0e, 0x96, 0x26 }; + { + 0x9f, 0x7f, 0x79, 0x47, 0x68, 0x91, 0x61, 0xb3, + 0x16, 0x7b, 0xf0, 0x27, 0x1c, 0xf7, 0xaf, 0x05, + 0x6c, 0xc1, 0x6f, 0xd2, 0xe7, 0xd1, 0xe9, 0xec, + 0x08, 0x87, 0xe5, 0xc8, 0x29, 0xa2, 0x5b, 0x84, + 0xf8, 0xa6, 0xec, 0x08, 0xf7, 0xcb, 0x7b, 0x6c, + 0xfe, 0x01, 0xfd, 0x5d, 0xba, 0xbf, 0x0d, 0x0f, + 0x2e, 0xef, 0xed, 0x7b, 0xfe, 0xc9, 0x4a, 0x85, + 0xcf, 0xac, 0x20, 0xd7, 0x01, 0xc5, 0xc5, 0x9c + }; boot_path = grub_util_get_path (dir, "fwstart.img"); boot_size = grub_util_get_image_size (boot_path); @@ -1588,9 +1590,19 @@ main (int argc, char *argv[]) + 1); memcpy (dir, GRUB_PKGLIBROOTDIR, sizeof (GRUB_PKGLIBROOTDIR) - 1); *(dir + sizeof (GRUB_PKGLIBROOTDIR) - 1) = '/'; - memcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), image_target->name, - last - image_target->name); - *(dir + sizeof (GRUB_PKGLIBROOTDIR) + (last - image_target->name)) = 0; + if (strncmp (image_target->name, "mipsel-yeeloong", + last - image_target->name) == 0) + { + memcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), "mips-yeeloong", + sizeof ("mips-yeeloong")); + } + else + { + memcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), image_target->name, + last - image_target->name); + *(dir + sizeof (GRUB_PKGLIBROOTDIR) + (last - image_target->name)) + = 0; + } } generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp, diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index fe1887f8f..dc2afdb6e 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -248,7 +248,7 @@ main (int argc, char *argv[]) { FILE *f; size_t rd; - f = fopen ("/dev/random", "rb"); + f = fopen ("/dev/urandom", "rb"); if (!f) { memset (pass1, 0, strlen (pass1)); diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index 455534009..f7f751708 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -160,7 +160,7 @@ process_input_dir () input_dir="$1" platform="$2" mkdir -p ${iso9660_dir}/boot/grub/${platform} - for file in ${input_dir}/*.mod; do + for file in "${input_dir}/"*.mod "${input_dir}/"efiemu32.o "${input_dir}/"efiemu64.o; do if test -f "$file"; then cp -f "$file" ${iso9660_dir}/boot/grub/${platform}/ fi diff --git a/util/grub-setup.c b/util/grub-setup.c index c1f2a1f5e..7d47fa654 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -520,9 +520,7 @@ unable_to_embed: core_path_dev = grub_make_system_path_relative_to_its_root (core_path_dev_full); free (core_path_dev_full); - /* It is a Good Thing to sync two times. */ - sync (); - sync (); + grub_util_biosdisk_flush (root_dev->disk); #define MAX_TRIES 5 @@ -583,7 +581,7 @@ unable_to_embed: grub_util_info ("error message = %s", grub_errmsg); grub_errno = GRUB_ERR_NONE; - sync (); + grub_util_biosdisk_flush (root_dev->disk); sleep (1); } @@ -674,8 +672,8 @@ unable_to_embed: grub_util_error ("%s", grub_errmsg); - /* Sync is a Good Thing. */ - sync (); + grub_util_biosdisk_flush (root_dev->disk); + grub_util_biosdisk_flush (dest_dev->disk); free (core_path); free (core_img); @@ -973,7 +971,15 @@ main (int argc, char *argv[]) char **devicelist; int i; - devicelist = grub_util_raid_getmembers (dest_dev); + if (arguments.device[0] == '/') + devicelist = grub_util_raid_getmembers (arguments.device); + else + { + char *devname; + devname = xasprintf ("/dev/%s", dest_dev); + devicelist = grub_util_raid_getmembers (dest_dev); + free (devname); + } for (i = 0; devicelist[i]; i++) { diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 420b3f32c..9da1511f5 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -132,6 +132,19 @@ if loadfont `make_system_path_relative_to_its_root "${GRUB_FONT_PATH}"` ; then set gfxmode=${GRUB_GFXMODE} load_video insmod gfxterm +EOF + +# Gettext variables and module +if [ "x${LANG}" != "xC" ] && [ -d "${locale_dir}" ] ; then + prepare_grub_to_access_device $(${grub_probe} --target=device ${locale_dir}) | sed -e "s/^/ /" + cat << EOF + set locale_dir=(\$root)$(make_system_path_relative_to_its_root ${locale_dir}) + set lang=${grub_lang} + insmod gettext +EOF +fi + +cat </dev/null || true`" = xbtrfs ]; then + rootsubvol="`make_system_path_relative_to_its_root /`" + rootsubvol="${rootsubvol#/}" + if [ "x${rootsubvol}" != x ]; then + GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}" + fi +fi + linux_entry () { os="$1" diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index 858627aa3..a9007603d 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -51,6 +51,14 @@ else LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} fi +if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`" = xbtrfs ]; then + rootsubvol="`make_system_path_relative_to_its_root /`" + rootsubvol="${rootsubvol#/}" + if [ "x${rootsubvol}" != x ]; then + GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}" + fi +fi + linux_entry () { os="$1" diff --git a/util/import_gcry.py b/util/import_gcry.py index 494a4ae7b..b2a0a5451 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -91,7 +91,12 @@ for cipher_file in cipher_files: f = open (infile, "r") fw = open (outfile, "w") fw.write ("/* This file was automatically imported with \n") - fw.write (" import_gcry.py. Please don't modify it */\n"); + fw.write (" import_gcry.py. Please don't modify it */\n") + fw.write ("#include \n") + # Whole libgcrypt is distributed under GPLv3+ or compatible + if isc: + fw.write ("GRUB_MOD_LICENSE (\"GPLv3+\");\n") + ciphernames = [] mdnames = [] hold = False diff --git a/util/raid.c b/util/raid.c index dac19a935..a6aa5f95e 100644 --- a/util/raid.c +++ b/util/raid.c @@ -36,25 +36,18 @@ #include char ** -grub_util_raid_getmembers (char *name) +grub_util_raid_getmembers (const char *name) { int fd, ret, i, j; - char *devname; char **devicelist; mdu_version_t version; mdu_array_info_t info; mdu_disk_info_t disk; - devname = xmalloc (strlen (name) + 6); - strcpy (devname, "/dev/"); - strcpy (devname+5, name); - - fd = open (devname, O_RDONLY); + fd = open (name, O_RDONLY); if (fd == -1) - grub_util_error ("can't open %s: %s", devname, strerror (errno)); - - free (devname); + grub_util_error ("can't open %s: %s", name, strerror (errno)); ret = ioctl (fd, RAID_VERSION, &version); if (ret != 0)