From 524a1e6a4067f347203694007b6c8bf427ae3235 Mon Sep 17 00:00:00 2001 From: okuji Date: Sun, 4 Jun 2006 15:56:55 +0000 Subject: [PATCH] 2006-06-04 Yoshinori K. Okuji Clean up the code to support 64-bit addressing in disks and files. This change is not enough for filesystems yet. * util/i386/pc/grub-setup.c (struct boot_blocklist): Change the type of "start" to grub_uint64_t. (setup): Change the types of KERNEL_SECTOR and FIRST_SECTOR to grub_disk_addr_t * and grub_disk_addr_t. Fix the format string in save_first_sector and save_blocklists. Use grub_le_to_cpu64 to convert addresses. * util/i386/pc/biosdisk.c (open_device): Change the type of SECTOR to grub_disk_addr_t. * partmap/gpt.c (gpt_partition_map_iterate): Fix the format string. * partmap/pc.c (pc_partition_map_iterate): Likewise. * partmap/amiga.c (amiga_partition_map_iterate): Cast RDSK.MAGIC to char *. * normal/script.c (grub_script_parse): Remove unused MEMFREE. * normal/parser.y (YYLTYPE_IS_TRIVIAL): New macro. * normal/lexer.c (grub_script_yyerror): Specify unused to LEX. * loader/i386/pc/multiboot.c (grub_multiboot_load_elf64): Cast -1 to grub_off_t, to detect an error from grub_file_seek. (grub_multiboot_load_elf32): Likewise. * kern/misc.c (grub_strtoul): Use grub_strtoull. Return the maximum unsigned long value when an overflow is detected. (grub_strtoull): New function. (grub_divmod64): Likewise. (grub_lltoa): use grub_divmod64. * kern/fs.c (struct grub_fs_block): Change the type of "offset" to grub_disk_addr_t. (grub_fs_blocklist_open): Increase P if P is not NULL to advance the pointer to next character. Use grub_strtoull instead of grub_strtoul. (grub_fs_blocklist_read): Change the types of SECTOR, OFFSET and SIZE to grub_disk_addr_t, grub_off_t and grub_size_t, respectively. * kern/file.c (grub_file_read): Prevent an oveflow of LEN, as the return value is signed. (grub_file_seek): Change the type of OLD to grub_off_t. Do not test if OFFSET is less than zero, as OFFSET is unsigned now. * kern/disk.c (struct grub_disk_cache): Change the type of "sector" to grub_disk_addr_t. (grub_disk_cache_get_index): Change the type of SECTOR to grub_disk_addr_t. Calculate the hash with SECTOR casted to unsigned after shifting. (grub_disk_cache_invalidate): Change the type of SECTOR to grub_disk_addr_t. (grub_disk_cache_unlock): Likewise. (grub_disk_cache_store): Likewise. (grub_disk_check_range): Change the types of SECTOR, OFFSET, SIZE, START and LEN to grub_disk_addr_t *, grub_off_t *, grub_size_t, grub_disk_addr_t and grub_uint64_t, respectively. (grub_disk_read): Use an unsigned variable REAL_OFFSET for the body, as the value of OFFSET is tweaked by grub_disk_check_range. Change the types of START_SECTOR, LEN and POS to grub_disk_addr_t, grub_size_t and grub_size_t, respectively. (grub_disk_write): Use an unsigned variable REAL_OFFSET for the body, as the value of OFFSET is tweaked by grub_disk_check_range. Change the types of LEN and N to grub_size_t. * io/gzio.c (struct grub_gzio): Change the types of "data_offset" and "saved_offset" to grub_off_t. (test_header): Cast BUF to char *. (get_byte): Cast GZIO->DATA_OFFSET to grub_off_t. Cast GZIO->INBUF to char *. (grub_gzio_read): Change the types of OFFSET and SIZE to grub_off_t and grub_size_t, respectively. * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_FORCE_LBA): Removed. (GRUB_BOOT_MACHINE_BOOT_DRIVE): Changed to 0x4c. (GRUB_BOOT_MACHINE_KERNEL_ADDRESS): Changed to 0x40. (GRUB_BOOT_MACHINE_KERNEL_SEGMENT): Changed to 0x42. (GRUB_BOOT_MACHINE_DRIVE_CHECK): Changed to 0x4e. (GRUB_BOOT_MACHINE_LIST_SIZE): Increased to 12. * include/grub/types.h (grub_off_t): Unconditionally set to grub_uint64_t. (grub_disk_addr_t): Changed to grub_uint64_t. * include/grub/partition.h (struct grub_partition): Change the types of "start", "len" and "offset" to grub_disk_addr_t, grub_uint64_t and grub_disk_addr_t, respectively. (grub_partition_get_start): Return grub_disk_addr_t. (grub_partition_get_len): Return grub_uint64_t. * include/grub/misc.h (grub_strtoull): New prototype. (grub_divmod64): Likewise. * include/grub/fshelp.h (grub_fshelp_read_file): Change the types of SECTOR, LEN and FILESIZE to grub_disk_addr_t, grub_size_t and grub_off_t, respectively. All callers and references changed. * include/grub/fs.h (struct grub_fs): Change the type of LEN to grub_size_t in "read". All callers and references changed. * include/grub/file.h (struct grub_file): Change the types of "offset" and "size" to grub_off_t and grub_off_t, respectively. Change the type of SECTOR to grub_disk_addr_t in "read_hook". (grub_file_read): Change the type of LEN to grub_size_t. (grub_file_seek): Return grub_off_t. Change the type of OFFSET to grub_off_t. (grub_file_size): Return grub_off_t. (grub_file_tell): Likewise. All callers and references changed. * include/grub/disk.h (struct grub_disk_dev): Change the types of SECTOR and SIZE to grub_disk_addr_t and grub_size_t in "read" and "write". (struct grub_disk): Change the type of "total_sectors" to grub_uint64_t. Change the type of SECTOR to grub_disk_addr_t in "read_hook". (grub_disk_read): Change the types of SECTOR, OFFSET and SIZE to grub_disk_addr_t, grub_off_t and grub_size_t, respectively. (grub_disk_write): Likewise. All callers and references changed. * fs/iso9660.c (grub_iso9660_susp_iterate): Cast parameters to char * for grub_strncmp to silence gcc. (grub_iso9660_mount): Likewise. (grub_iso9660_mount): Likewise. (grub_iso9660_read_symlink): Likewise. Also, remove the nonsense return statement. (grub_iso9660_iterate_dir): Likewise. (grub_iso9660_label): Cast DATA->VOLDESC.VOLNAME to char *. * fs/hfs.c (grub_hfs_read_file): Change the types of SECTOR and LEN to grub_disk_addr_t and grub_size_t, respectively. * fs/hfsplus.c (grub_hfsplus_read_file): Likewise. * fs/jfs.c (grub_jfs_read_file): Likewise. * fs/minix.c (grub_jfs_read_file): Likewise. * fs/sfs.c (grub_jfs_read_file): Likewise. * fs/ufs.c (grub_jfs_read_file): Likewise. * fs/xfs.c (grub_jfs_read_file): Likewise. * fs/fat.c (grub_fat_read_data): Change the types of SECTOR, LEN and SIZE to grub_disk_addr_t, grub_size_t and grub_size_t, respectively. * fs/ext2.c (grub_ext2_read_block): When an error happens, set BLKNR to -1 instead of returning GRUB_ERRNO. (grub_ext2_read_file): Change the types of SECTOR and LEN to grub_disk_addr_t and grub_size_t, respectively. * fs/affs.c (grub_affs_read_file): Change the types of SECTOR and LEN to grub_disk_addr_t and grub_size_t, respectively. * font/manager.c (grub_font_get_glyph): Cast BITMAP to char * for grub_file_read. * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Fix the format string. Do not cast SECTOR explicitly. * disk/i386/pc/biosdisk.c (grub_biosdisk_open): Change the type of TOTAL_SECTORS to grub_uint64_t. Do not mask DRP->TOTAL_SECTORS. (grub_biosdisk_rw): Change the types of SECTOR and SIZE to grub_disk_addr_t and grub_size_t, respectively. If the sector is over 2TB and LBA mode is not supported, raise an error. (get_safe_sectors): New function. (grub_biosdisk_read): Use get_safe_sectors. (grub_biosdisk_write): Likewise. * disk/efi/efidisk.c (grub_efidisk_read): Fix the format string. (grub_efidisk_write): Likewise. * disk/loopback.c (delete_loopback): Cosmetic changes. (grub_cmd_loopback): Likewise. Also, test NEWDEV->FILENAME correctly. (grub_loopback_open): Likewise. (grub_loopback_read): Likewise. Also, change the type of POS to grub_off_t, and fix the usage of grub_memset. * commands/i386/pc/play.c: Include grub/machine/time.h. * commands/ls.c (grub_ls_list_files): Use "llu" instead of "d" to print FILE->SIZE. * commands/configfile.c: Include grub/env.h. * commands/cmp.c (grub_cmd_cmp): Do not use ERR, but use GRUB_ERRNO directly instead. Change the type of POS to grub_off_t. Follow the coding standard. * commands/blocklist.c: Include grub/partition.h. (grub_cmd_blocklist): Return an error if the underlying device is not a disk. Take the starting sector of a partition into account, if a partition is used. * boot/i386/pc/diskboot.S (bootloop): Adapted to the new offset of a length field. (lba_mode): Support 64-bit addresses. (chs_mode): Likewise. (copy_buffer): Adapted to the new offsets of a length field and a segment field. (blocklist_default_start): Allocate 64-bit space. * boot/i386/pc/boot.S (force_lba): Removed. (boot_drive): Moved to under KERNEL_SECTOR. (kernel_sector): Moved to under KENREL_SEGMENT. Allocate 64-bit space. (real_start): Set %si earlier. Remove code for FORCE_LBA, since it is useless. (lba_mode): Refactored to support a 64-bit address. More size optimization. (setup_sectors): Likewise. --- ChangeLog | 230 ++++++++++++++++++++++++++++++++++++ boot/i386/pc/boot.S | 95 +++++++-------- boot/i386/pc/diskboot.S | 44 +++---- commands/blocklist.c | 19 ++- commands/cmp.c | 31 +++-- commands/configfile.c | 1 + commands/i386/pc/play.c | 1 + commands/ls.c | 4 +- disk/efi/efidisk.c | 14 ++- disk/i386/pc/biosdisk.c | 56 ++++++--- disk/ieee1275/ofdisk.c | 20 ++-- disk/loopback.c | 48 ++++---- font/manager.c | 2 +- fs/affs.c | 8 +- fs/ext2.c | 8 +- fs/fat.c | 8 +- fs/fshelp.c | 8 +- fs/hfs.c | 8 +- fs/hfsplus.c | 6 +- fs/iso9660.c | 35 +++--- fs/jfs.c | 8 +- fs/minix.c | 8 +- fs/sfs.c | 8 +- fs/ufs.c | 6 +- fs/xfs.c | 8 +- include/grub/disk.h | 28 +++-- include/grub/file.h | 16 +-- include/grub/fs.h | 2 +- include/grub/fshelp.h | 8 +- include/grub/i386/pc/boot.h | 15 +-- include/grub/misc.h | 3 + include/grub/partition.h | 15 +-- include/grub/types.h | 9 +- io/gzio.c | 24 ++-- kern/disk.c | 87 ++++++++------ kern/file.c | 16 ++- kern/fs.c | 14 ++- kern/misc.c | 98 ++++++++++----- loader/i386/pc/multiboot.c | 6 +- normal/lexer.c | 3 +- normal/parser.y | 2 +- normal/script.c | 1 - partmap/amiga.c | 4 +- partmap/gpt.c | 4 +- partmap/pc.c | 4 +- util/i386/pc/biosdisk.c | 12 +- util/i386/pc/grub-setup.c | 33 +++--- 47 files changed, 708 insertions(+), 380 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3651841d..5f944efbe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,233 @@ +2006-06-04 Yoshinori K. Okuji + + Clean up the code to support 64-bit addressing in disks and + files. This change is not enough for filesystems yet. + + * util/i386/pc/grub-setup.c (struct boot_blocklist): Change the + type of "start" to grub_uint64_t. + (setup): Change the types of KERNEL_SECTOR and FIRST_SECTOR to + grub_disk_addr_t * and grub_disk_addr_t. Fix the format string in + save_first_sector and save_blocklists. Use grub_le_to_cpu64 to + convert addresses. + + * util/i386/pc/biosdisk.c (open_device): Change the type of SECTOR + to grub_disk_addr_t. + + * partmap/gpt.c (gpt_partition_map_iterate): Fix the format + string. + + * partmap/pc.c (pc_partition_map_iterate): Likewise. + + * partmap/amiga.c (amiga_partition_map_iterate): Cast RDSK.MAGIC + to char *. + + * normal/script.c (grub_script_parse): Remove unused MEMFREE. + + * normal/parser.y (YYLTYPE_IS_TRIVIAL): New macro. + + * normal/lexer.c (grub_script_yyerror): Specify unused to LEX. + + * loader/i386/pc/multiboot.c (grub_multiboot_load_elf64): Cast -1 + to grub_off_t, to detect an error from grub_file_seek. + (grub_multiboot_load_elf32): Likewise. + + * kern/misc.c (grub_strtoul): Use grub_strtoull. Return the + maximum unsigned long value when an overflow is detected. + (grub_strtoull): New function. + (grub_divmod64): Likewise. + (grub_lltoa): use grub_divmod64. + + * kern/fs.c (struct grub_fs_block): Change the type of "offset" to + grub_disk_addr_t. + (grub_fs_blocklist_open): Increase P if P is not NULL to advance + the pointer to next character. Use grub_strtoull instead of + grub_strtoul. + (grub_fs_blocklist_read): Change the types of SECTOR, OFFSET and + SIZE to grub_disk_addr_t, grub_off_t and grub_size_t, + respectively. + + * kern/file.c (grub_file_read): Prevent an oveflow of LEN, as the + return value is signed. + (grub_file_seek): Change the type of OLD to grub_off_t. Do not + test if OFFSET is less than zero, as OFFSET is unsigned now. + + * kern/disk.c (struct grub_disk_cache): Change the type of + "sector" to grub_disk_addr_t. + (grub_disk_cache_get_index): Change the type of SECTOR to + grub_disk_addr_t. Calculate the hash with SECTOR casted to + unsigned after shifting. + (grub_disk_cache_invalidate): Change the type of SECTOR to + grub_disk_addr_t. + (grub_disk_cache_unlock): Likewise. + (grub_disk_cache_store): Likewise. + (grub_disk_check_range): Change the types of SECTOR, OFFSET, SIZE, + START and LEN to grub_disk_addr_t *, grub_off_t *, grub_size_t, + grub_disk_addr_t and grub_uint64_t, respectively. + (grub_disk_read): Use an unsigned variable REAL_OFFSET for the + body, as the value of OFFSET is tweaked by + grub_disk_check_range. Change the types of START_SECTOR, LEN and + POS to grub_disk_addr_t, grub_size_t and grub_size_t, + respectively. + (grub_disk_write): Use an unsigned variable REAL_OFFSET for the + body, as the value of OFFSET is tweaked by + grub_disk_check_range. Change the types of LEN and N to + grub_size_t. + + * io/gzio.c (struct grub_gzio): Change the types of "data_offset" + and "saved_offset" to grub_off_t. + (test_header): Cast BUF to char *. + (get_byte): Cast GZIO->DATA_OFFSET to grub_off_t. Cast GZIO->INBUF + to char *. + (grub_gzio_read): Change the types of OFFSET and SIZE to + grub_off_t and grub_size_t, respectively. + + * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_FORCE_LBA): + Removed. + (GRUB_BOOT_MACHINE_BOOT_DRIVE): Changed to 0x4c. + (GRUB_BOOT_MACHINE_KERNEL_ADDRESS): Changed to 0x40. + (GRUB_BOOT_MACHINE_KERNEL_SEGMENT): Changed to 0x42. + (GRUB_BOOT_MACHINE_DRIVE_CHECK): Changed to 0x4e. + (GRUB_BOOT_MACHINE_LIST_SIZE): Increased to 12. + + * include/grub/types.h (grub_off_t): Unconditionally set to + grub_uint64_t. + (grub_disk_addr_t): Changed to grub_uint64_t. + + * include/grub/partition.h (struct grub_partition): Change the + types of "start", "len" and "offset" to grub_disk_addr_t, + grub_uint64_t and grub_disk_addr_t, respectively. + (grub_partition_get_start): Return grub_disk_addr_t. + (grub_partition_get_len): Return grub_uint64_t. + + * include/grub/misc.h (grub_strtoull): New prototype. + (grub_divmod64): Likewise. + + * include/grub/fshelp.h (grub_fshelp_read_file): Change the types + of SECTOR, LEN and FILESIZE to grub_disk_addr_t, grub_size_t and + grub_off_t, respectively. + All callers and references changed. + + * include/grub/fs.h (struct grub_fs): Change the type of LEN to + grub_size_t in "read". + All callers and references changed. + + * include/grub/file.h (struct grub_file): Change the types of + "offset" and "size" to grub_off_t and grub_off_t, + respectively. Change the type of SECTOR to grub_disk_addr_t in + "read_hook". + (grub_file_read): Change the type of LEN to grub_size_t. + (grub_file_seek): Return grub_off_t. Change the type of OFFSET to + grub_off_t. + (grub_file_size): Return grub_off_t. + (grub_file_tell): Likewise. + All callers and references changed. + + * include/grub/disk.h (struct grub_disk_dev): Change the types of + SECTOR and SIZE to grub_disk_addr_t and grub_size_t in "read" and + "write". + (struct grub_disk): Change the type of "total_sectors" to + grub_uint64_t. Change the type of SECTOR to grub_disk_addr_t in + "read_hook". + (grub_disk_read): Change the types of SECTOR, OFFSET and SIZE to + grub_disk_addr_t, grub_off_t and grub_size_t, respectively. + (grub_disk_write): Likewise. + All callers and references changed. + + * fs/iso9660.c (grub_iso9660_susp_iterate): Cast parameters to + char * for grub_strncmp to silence gcc. + (grub_iso9660_mount): Likewise. + (grub_iso9660_mount): Likewise. + (grub_iso9660_read_symlink): Likewise. Also, remove the nonsense + return statement. + (grub_iso9660_iterate_dir): Likewise. + (grub_iso9660_label): Cast DATA->VOLDESC.VOLNAME to char *. + + * fs/hfs.c (grub_hfs_read_file): Change the types of SECTOR and + LEN to grub_disk_addr_t and grub_size_t, respectively. + + * fs/hfsplus.c (grub_hfsplus_read_file): Likewise. + + * fs/jfs.c (grub_jfs_read_file): Likewise. + + * fs/minix.c (grub_jfs_read_file): Likewise. + + * fs/sfs.c (grub_jfs_read_file): Likewise. + + * fs/ufs.c (grub_jfs_read_file): Likewise. + + * fs/xfs.c (grub_jfs_read_file): Likewise. + + * fs/fat.c (grub_fat_read_data): Change the types of SECTOR, LEN + and SIZE to grub_disk_addr_t, grub_size_t and grub_size_t, + respectively. + + * fs/ext2.c (grub_ext2_read_block): When an error happens, set + BLKNR to -1 instead of returning GRUB_ERRNO. + (grub_ext2_read_file): Change the types of SECTOR and + LEN to grub_disk_addr_t and grub_size_t, respectively. + + * fs/affs.c (grub_affs_read_file): Change the types of SECTOR and + LEN to grub_disk_addr_t and grub_size_t, respectively. + + * font/manager.c (grub_font_get_glyph): Cast BITMAP to char * for + grub_file_read. + + * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Fix the format + string. Do not cast SECTOR explicitly. + + * disk/i386/pc/biosdisk.c (grub_biosdisk_open): Change the type of + TOTAL_SECTORS to grub_uint64_t. Do not mask DRP->TOTAL_SECTORS. + (grub_biosdisk_rw): Change the types of SECTOR and SIZE to + grub_disk_addr_t and grub_size_t, respectively. If the sector is + over 2TB and LBA mode is not supported, raise an error. + (get_safe_sectors): New function. + (grub_biosdisk_read): Use get_safe_sectors. + (grub_biosdisk_write): Likewise. + + * disk/efi/efidisk.c (grub_efidisk_read): Fix the format string. + (grub_efidisk_write): Likewise. + + * disk/loopback.c (delete_loopback): Cosmetic changes. + (grub_cmd_loopback): Likewise. Also, test NEWDEV->FILENAME + correctly. + (grub_loopback_open): Likewise. + (grub_loopback_read): Likewise. Also, change the type of POS to + grub_off_t, and fix the usage of grub_memset. + + * commands/i386/pc/play.c: Include grub/machine/time.h. + + * commands/ls.c (grub_ls_list_files): Use "llu" instead of "d" to + print FILE->SIZE. + + * commands/configfile.c: Include grub/env.h. + + * commands/cmp.c (grub_cmd_cmp): Do not use ERR, but use + GRUB_ERRNO directly instead. Change the type of POS to + grub_off_t. Follow the coding standard. + + * commands/blocklist.c: Include grub/partition.h. + (grub_cmd_blocklist): Return an error if the underlying device is + not a disk. Take the starting sector of a partition into account, + if a partition is used. + + * boot/i386/pc/diskboot.S (bootloop): Adapted to the new offset of + a length field. + (lba_mode): Support 64-bit addresses. + (chs_mode): Likewise. + (copy_buffer): Adapted to the new offsets of a length field and a + segment field. + (blocklist_default_start): Allocate 64-bit space. + + * boot/i386/pc/boot.S (force_lba): Removed. + (boot_drive): Moved to under KERNEL_SECTOR. + (kernel_sector): Moved to under KENREL_SEGMENT. Allocate 64-bit + space. + (real_start): Set %si earlier. Remove code for FORCE_LBA, since it + is useless. + (lba_mode): Refactored to support a 64-bit address. More size + optimization. + (setup_sectors): Likewise. + 2006-06-04 Yoshinori K. Okuji * DISTLIST: Added include/grub/i386/linux.h. Removed diff --git a/boot/i386/pc/boot.S b/boot/i386/pc/boot.S index b63079930..8a65ff965 100644 --- a/boot/i386/pc/boot.S +++ b/boot/i386/pc/boot.S @@ -1,7 +1,7 @@ /* -*-Asm-*- */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2005 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -91,17 +91,15 @@ cylinder_start: boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR +kernel_address: + .word GRUB_BOOT_MACHINE_KERNEL_ADDR +kernel_segment: + .word GRUB_BOOT_MACHINE_KERNEL_SEG +kernel_sector: + .long 1, 0 boot_drive: .byte 0xff /* the disk to load kernel from */ /* 0xff means use the boot drive */ -force_lba: - .byte 0 -kernel_address: - .word GRUB_BOOT_MACHINE_KERNEL_ADDR -kernel_sector: - .long 1 -kernel_segment: - .word GRUB_BOOT_MACHINE_KERNEL_SEG after_BPB: @@ -155,6 +153,9 @@ real_start: /* print a notification message on the screen */ MSG(notification_string) + /* set %si to the disk address packet */ + movw $ABS(disk_address_packet), %si + /* do not probe LBA if the drive is a floppy */ testb $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl jz chs_mode @@ -176,35 +177,28 @@ real_start: cmpw $0xaa55, %bx jne chs_mode - /* set %si to the disk address packet */ - movw $ABS(disk_address_packet), %si - - /* check if AH=0x42 is supported if FORCE_LBA is zero */ - MOV_MEM_TO_AL(ABS(force_lba)) /* movb ABS(force_lba), %al */ - testb %al, %al - jnz lba_mode andw $1, %cx jz chs_mode lba_mode: - xorl %eax, %eax + xorw %ax, %ax movw %ax, 4(%si) - movl %eax, 12(%si) incw %ax /* set the mode to non-zero */ movb %al, -1(%si) - movl ABS(kernel_sector), %ebx + /* the blocks */ + movw %ax, 2(%si) /* the size and the reserved byte */ movw $0x0010, (%si) - /* the blocks */ - movw %ax, 2(%si) - - /* the absolute address (low 32 bits) */ + /* the absolute address */ + movl ABS(kernel_sector), %ebx movl %ebx, 8(%si) + movl ABS(kernel_sector + 4), %ebx + movl %ebx, 12(%si) /* the segment of buffer address */ movw $GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si) @@ -247,16 +241,14 @@ chs_mode: final_init: /* set the mode to zero */ - movb $0, -1(%si) + movzbl %dh, %eax + movb %ah, -1(%si) /* save number of heads */ - xorl %eax, %eax - movb %dh, %al incw %ax movl %eax, 4(%si) - xorw %dx, %dx - movb %cl, %dl + movzbw %cl, %dx shlw $2, %dx movb %ch, %al movb %dh, %ah @@ -265,14 +257,18 @@ final_init: incw %ax movw %ax, 8(%si) - xorw %ax, %ax - movb %dl, %al + movzbw %dl, %ax shrb $2, %al /* save number of sectors */ movl %eax, (%si) setup_sectors: + /* load logical sector start (top half) */ + movl ABS(kernel_sector + 4), %eax + orl %eax, %eax + jnz geometry_error + /* load logical sector start (bottom half) */ movl ABS(kernel_sector), %eax @@ -283,41 +279,34 @@ setup_sectors: divl (%si) /* save sector start */ - movb %dl, 10(%si) + movb %dl, %cl - xorl %edx, %edx /* zero %edx */ + xorw %dx, %dx /* zero %edx */ divl 4(%si) /* divide by number of heads */ - /* save head start */ - movb %dl, 11(%si) - - /* save cylinder start */ - movw %ax, 12(%si) - /* do we need too many cylinders? */ cmpw 8(%si), %ax jge geometry_error -/* - * This is the loop for taking care of BIOS geometry translation (ugh!) - */ + /* normalize sector start (1-based) */ + incb %cl - /* get high bits of cylinder */ - movb 13(%si), %dl + /* low bits of cylinder start */ + movb %al, %ch - shlb $6, %dl /* shift left by 6 bits */ - movb 10(%si), %cl /* get sector */ + /* high bits of cylinder start */ + xorb %al, %al + shrw $2, %ax + orb %al, %cl - incb %cl /* normalize sector (sectors go - from 1-N, not 0-(N-1) ) */ - orb %dl, %cl /* composite together */ - movb 12(%si), %ch /* sector+hcyl in cl, cylinder in ch */ + /* save head start */ + movb %dl, %al - /* restore %dx */ + /* restore %dl */ popw %dx - - /* head number */ - movb 11(%si), %dh + + /* head start */ + movb %al, %dh /* * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory diff --git a/boot/i386/pc/diskboot.S b/boot/i386/pc/diskboot.S index c2a0e0ccd..c267d1f40 100644 --- a/boot/i386/pc/diskboot.S +++ b/boot/i386/pc/diskboot.S @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -71,7 +71,7 @@ _start: bootloop: /* check the number of sectors to read */ - cmpw $0, 4(%di) + cmpw $0, 8(%di) /* if zero, go to the start function */ je bootit @@ -86,26 +86,28 @@ setup_sectors: lba_mode: /* load logical sector start */ movl (%di), %ebx + movl 4(%di), %ecx /* the maximum is limited to 0x7f because of Phoenix EDD */ xorl %eax, %eax movb $0x7f, %al /* how many do we really want to read? */ - cmpw %ax, 4(%di) /* compare against total number of sectors */ + cmpw %ax, 8(%di) /* compare against total number of sectors */ /* which is greater? */ jg 1f /* if less than, set to total */ - movw 4(%di), %ax + movw 8(%di), %ax 1: /* subtract from total */ - subw %ax, 4(%di) + subw %ax, 8(%di) /* add into logical sector start */ addl %eax, (%di) + adcl $0, 4(%di) /* set up disk address packet */ @@ -115,8 +117,9 @@ lba_mode: /* the number of sectors */ movw %ax, 2(%si) - /* the absolute address (low 32 bits) */ + /* the absolute address */ movl %ebx, 8(%si) + movl %ecx, 12(%si) /* the segment of buffer address */ movw $GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si) @@ -124,15 +127,8 @@ lba_mode: /* save %ax from destruction! */ pushw %ax - /* zero %eax */ - xorl %eax, %eax - /* the offset of buffer address */ - movw %ax, 4(%si) - - /* the absolute address (high 32 bits) */ - movl %eax, 12(%si) - + movw $0, 4(%si) /* * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory @@ -152,6 +148,11 @@ lba_mode: jmp copy_buffer chs_mode: + /* load logical sector start (top half) */ + movl 4(%di), %eax + orl %eax, %eax + jnz geometry_error + /* load logical sector start (bottom half) */ movl (%di), %eax @@ -184,21 +185,22 @@ chs_mode: subb 10(%si), %al /* how many do we really want to read? */ - cmpw %ax, 4(%di) /* compare against total number of sectors */ + cmpw %ax, 8(%di) /* compare against total number of sectors */ /* which is greater? */ jg 2f /* if less than, set to total */ - movw 4(%di), %ax + movw 8(%di), %ax 2: /* subtract from total */ - subw %ax, 4(%di) + subw %ax, 8(%di) /* add into logical sector start */ addl %eax, (%di) + adcl $0, 4(%di) /* * This is the loop for taking care of BIOS geometry translation (ugh!) @@ -252,7 +254,7 @@ chs_mode: copy_buffer: /* load addresses for copy from disk buffer to destination */ - movw 6(%di), %es /* load destination segment */ + movw 10(%di), %es /* load destination segment */ /* restore %ax */ popw %ax @@ -260,7 +262,7 @@ copy_buffer: /* determine the next possible destination address (presuming 512 byte sectors!) */ shlw $5, %ax /* shift %ax five bits to the left */ - addw %ax, 6(%di) /* add the corrected value to the destination + addw %ax, 10(%di) /* add the corrected value to the destination address for next time */ /* save addressing regs */ @@ -288,7 +290,7 @@ copy_buffer: popa /* check if finished with this dataset */ - cmpw $0, 4(%di) + cmpw $0, 8(%di) jne setup_sectors /* update position to load from */ @@ -374,7 +376,7 @@ lastlist: blocklist_default_start: /* this is the sector start parameter, in logical sectors from the start of the disk, sector 0 */ - .long 2 + .long 2, 0 blocklist_default_len: /* this is the number of sectors to read the command "install" will fill this up */ diff --git a/commands/blocklist.c b/commands/blocklist.c index ec8233ab6..e6d84cf42 100644 --- a/commands/blocklist.c +++ b/commands/blocklist.c @@ -25,6 +25,7 @@ #include #include #include +#include static grub_err_t grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)), @@ -35,12 +36,13 @@ grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)), unsigned long start_sector = 0; unsigned num_sectors = 0; int num_entries = 0; - auto void read_blocklist (unsigned long sector, unsigned offset, + grub_disk_addr_t part_start = 0; + auto void read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length); - auto void print_blocklist (unsigned long sector, unsigned num, + auto void print_blocklist (grub_disk_addr_t sector, unsigned num, unsigned offset, unsigned length); - void read_blocklist (unsigned long sector, unsigned offset, + void read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length) { if (num_sectors > 0) @@ -65,13 +67,13 @@ grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)), print_blocklist (sector, 0, offset, length); } - void print_blocklist (unsigned long sector, unsigned num, + void print_blocklist (grub_disk_addr_t sector, unsigned num, unsigned offset, unsigned length) { if (num_entries++) grub_printf (","); - grub_printf ("%lu", sector); + grub_printf ("%llu", sector - part_start); if (num > 0) grub_printf ("+%u", num); if (offset != 0 || length != 0) @@ -85,6 +87,13 @@ grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)), if (! file) return grub_errno; + if (! file->device->disk) + return grub_error (GRUB_ERR_BAD_DEVICE, + "this command is available only for disk devices."); + + if (file->device->disk->partition) + part_start = grub_partition_get_start (file->device->disk->partition); + file->read_hook = read_blocklist; while (grub_file_read (file, buf, sizeof (buf)) > 0) diff --git a/commands/cmp.c b/commands/cmp.c index 4bc420c4e..a2a563a44 100644 --- a/commands/cmp.c +++ b/commands/cmp.c @@ -1,7 +1,7 @@ /* cmd.c - command to cmp an operating system */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003,2005 Free Software Foundation, Inc. + * Copyright (C) 2003,2005,2006 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 @@ -32,9 +32,8 @@ static grub_err_t grub_cmd_cmp (struct grub_arg_list *state __attribute__ ((unused)), int argc, char **args) { - grub_err_t err; grub_ssize_t rd1, rd2; - grub_uint32_t pos; + grub_off_t pos; grub_file_t file1 = 0; grub_file_t file2 = 0; char *buf1 = 0; @@ -46,25 +45,29 @@ grub_cmd_cmp (struct grub_arg_list *state __attribute__ ((unused)), grub_printf ("Compare `%s' and `%s':\n", args[0], args[1]); - if (! (file1 = grub_gzfile_open (args[0], 1) ) || - ! (file2 = grub_gzfile_open (args[1], 1) ) ) + file1 = grub_gzfile_open (args[0], 1); + file2 = grub_gzfile_open (args[1], 1); + if (! file1 || ! file2) goto cleanup; if (grub_file_size (file1) != grub_file_size (file2)) - grub_printf ("Differ in size: %d [%s], %d [%s]\n", + grub_printf ("Differ in size: %llu [%s], %llu [%s]\n", grub_file_size (file1), args[0], grub_file_size (file2), args[1]); - else { pos = 0; - if (! (buf1 = (char *) grub_malloc (BUFFER_SIZE) ) || - ! (buf2 = (char *) grub_malloc (BUFFER_SIZE) ) ) + buf1 = grub_malloc (BUFFER_SIZE); + buf2 = grub_malloc (BUFFER_SIZE); + + if (! buf1 || ! buf2) goto cleanup; + do { int i; + rd1 = grub_file_read (file1, buf1, BUFFER_SIZE); rd2 = grub_file_read (file2, buf2, BUFFER_SIZE); @@ -75,7 +78,7 @@ grub_cmd_cmp (struct grub_arg_list *state __attribute__ ((unused)), { if (buf1[i] != buf2[i]) { - grub_printf ("Differ at the offset %d: 0x%x [%s], 0x%x [%s]\n", + grub_printf ("Differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n", i + pos, buf1[i], args[0], buf2[i], args[1]); goto cleanup; @@ -83,12 +86,14 @@ grub_cmd_cmp (struct grub_arg_list *state __attribute__ ((unused)), } pos += BUFFER_SIZE; - } while (rd2); + } + while (rd2); + grub_printf ("The files are identical.\n"); } cleanup: - err=grub_errno; + if (buf1) grub_free (buf1); if (buf2) @@ -98,7 +103,7 @@ cleanup: if (file2) grub_file_close (file2); - return err; + return grub_errno; } diff --git a/commands/configfile.c b/commands/configfile.c index 81ca70e7a..d52829a40 100644 --- a/commands/configfile.c +++ b/commands/configfile.c @@ -23,6 +23,7 @@ #include #include #include +#include static grub_err_t grub_cmd_configfile (struct grub_arg_list *state __attribute__ ((unused)), diff --git a/commands/i386/pc/play.c b/commands/i386/pc/play.c index f3f524b50..987531c5b 100644 --- a/commands/i386/pc/play.c +++ b/commands/i386/pc/play.c @@ -27,6 +27,7 @@ #include #include #include +#include #define BASE_TEMPO 120 diff --git a/commands/ls.c b/commands/ls.c index 547e4b325..0e2e14f6b 100644 --- a/commands/ls.c +++ b/commands/ls.c @@ -106,7 +106,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) } if (! human) - grub_printf ("%-12d", file->size); + grub_printf ("%-12llu", file->size); else { float fsize = file->size; @@ -127,7 +127,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) grub_printf ("%-12s", buf); } else - grub_printf ("%-12d", file->size); + grub_printf ("%-12llu", file->size); } grub_file_close (file); diff --git a/disk/efi/efidisk.c b/disk/efi/efidisk.c index 8b8b9fa8d..87ee6de43 100644 --- a/disk/efi/efidisk.c +++ b/disk/efi/efidisk.c @@ -558,8 +558,8 @@ grub_efidisk_close (struct grub_disk *disk __attribute__ ((unused))) } static grub_err_t -grub_efidisk_read (struct grub_disk *disk, unsigned long sector, - unsigned long size, char *buf) +grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) { /* For now, use the disk io interface rather than the block io's. */ struct grub_efidisk_data *d; @@ -571,7 +571,8 @@ grub_efidisk_read (struct grub_disk *disk, unsigned long sector, dio = d->disk_io; bio = d->block_io; - grub_dprintf ("efidisk", "reading 0x%lx sectors at the sector 0x%lx from %s\n", + grub_dprintf ("efidisk", + "reading 0x%x sectors at the sector 0x%llx from %s\n", size, sector, disk->name); status = dio->read (dio, bio->media->media_id, @@ -585,8 +586,8 @@ grub_efidisk_read (struct grub_disk *disk, unsigned long sector, } static grub_err_t -grub_efidisk_write (struct grub_disk *disk, unsigned long sector, - unsigned long size, const char *buf) +grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) { /* For now, use the disk io interface rather than the block io's. */ struct grub_efidisk_data *d; @@ -598,7 +599,8 @@ grub_efidisk_write (struct grub_disk *disk, unsigned long sector, dio = d->disk_io; bio = d->block_io; - grub_dprintf ("efidisk", "writing 0x%lx sectors at the sector 0x%lx to %s\n", + grub_dprintf ("efidisk", + "writing 0x%x sectors at the sector 0x%llx to %s\n", size, sector, disk->name); status = dio->write (dio, bio->media->media_id, diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c index fc73eff9e..3382ab445 100644 --- a/disk/i386/pc/biosdisk.c +++ b/disk/i386/pc/biosdisk.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006 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 @@ -126,7 +126,7 @@ grub_biosdisk_iterate (int (*hook) (const char *name)) static grub_err_t grub_biosdisk_open (const char *name, grub_disk_t disk) { - unsigned long total_sectors = 0; + grub_uint64_t total_sectors = 0; int drive; struct grub_biosdisk_data *data; @@ -158,13 +158,12 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) /* Clear out the DRP. */ grub_memset (drp, 0, sizeof (*drp)); drp->size = sizeof (*drp); - if (!grub_biosdisk_get_diskinfo_int13_extensions (drive, drp)) + if (! grub_biosdisk_get_diskinfo_int13_extensions (drive, drp)) { data->flags = GRUB_BIOSDISK_FLAG_LBA; - /* FIXME: 2TB limit. */ if (drp->total_sectors) - total_sectors = drp->total_sectors & ~0L; + total_sectors = drp->total_sectors; else /* Some buggy BIOSes doesn't return the total sectors correctly but returns zero. So if it is zero, compute @@ -204,7 +203,7 @@ grub_biosdisk_close (grub_disk_t disk) static grub_err_t grub_biosdisk_rw (int cmd, grub_disk_t disk, - unsigned long sector, unsigned long size, + grub_disk_addr_t sector, grub_size_t size, unsigned segment) { struct grub_biosdisk_data *data = disk->data; @@ -234,9 +233,15 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, { unsigned coff, hoff, soff; unsigned head; + unsigned real_sector = (unsigned) sector; - soff = sector % data->sectors + 1; - head = sector / data->sectors; + /* It is impossible to reach over 2TB with the traditional + CHS access. */ + if (sector > ~0UL) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk"); + + soff = real_sector % data->sectors + 1; + head = real_sector / data->sectors; hoff = head % data->heads; coff = head / data->heads; @@ -259,17 +264,36 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, return GRUB_ERR_NONE; } +/* Return the number of sectors which can be read safely at a time. */ +static grub_size_t +get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors) +{ + grub_size_t size; + grub_uint32_t offset; + + /* OFFSET = SECTOR % SECTORS */ + grub_divmod64 (sector, sectors, &offset); + + size = sectors - offset; + + /* Limit the max to 0x7f because of Phoenix EDD. */ + if (size > 0x7f) + size = 0x7f; + + return size; +} + static grub_err_t -grub_biosdisk_read (grub_disk_t disk, unsigned long sector, - unsigned long size, char *buf) +grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) { struct grub_biosdisk_data *data = disk->data; while (size) { - unsigned long len; + grub_size_t len; - len = data->sectors - (sector % data->sectors); + len = get_safe_sectors (sector, data->sectors); if (len > size) len = size; @@ -288,16 +312,16 @@ grub_biosdisk_read (grub_disk_t disk, unsigned long sector, } static grub_err_t -grub_biosdisk_write (grub_disk_t disk, unsigned long sector, - unsigned long size, const char *buf) +grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) { struct grub_biosdisk_data *data = disk->data; while (size) { - unsigned long len; + grub_size_t len; - len = data->sectors - (sector % data->sectors); + len = get_safe_sectors (sector, data->sectors); if (len > size) len = size; diff --git a/disk/ieee1275/ofdisk.c b/disk/ieee1275/ofdisk.c index 6b0412cce..7a803d40c 100644 --- a/disk/ieee1275/ofdisk.c +++ b/disk/ieee1275/ofdisk.c @@ -1,7 +1,7 @@ /* ofdisk.c - Open Firmware disk access. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004 Free Software Foundation, Inc. + * Copyright (C) 2004,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -122,35 +122,37 @@ grub_ofdisk_close (grub_disk_t disk) } static grub_err_t -grub_ofdisk_read (grub_disk_t disk, unsigned long sector, - unsigned long size, char *buf) +grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) { grub_ssize_t status, actual; unsigned long long pos; grub_dprintf ("disk", - "Reading handle %p: sector 0x%lx, size 0x%lx, buf %p.\n", + "Reading handle %p: sector 0x%llx, size 0x%lx, buf %p.\n", (void *) disk->data, sector, size, buf); - pos = (unsigned long long) sector * 512UL; + pos = sector * 512UL; grub_ieee1275_seek ((grub_ieee1275_ihandle_t) disk->data, (int) (pos >> 32), (int) pos & 0xFFFFFFFFUL, &status); if (status != 0) return grub_error (GRUB_ERR_READ_ERROR, - "Seek error, can't seek block %d", sector); + "Seek error, can't seek block %llu", + sector); grub_ieee1275_read ((grub_ieee1275_ihandle_t) disk->data, buf, size * 512UL, &actual); if (actual != actual) - return grub_error (GRUB_ERR_READ_ERROR, "Read error on block: %d", sector); + return grub_error (GRUB_ERR_READ_ERROR, "Read error on block: %llu", + sector); return 0; } static grub_err_t grub_ofdisk_write (grub_disk_t disk __attribute ((unused)), - unsigned long sector __attribute ((unused)), - unsigned long size __attribute ((unused)), + grub_disk_addr_t sector __attribute ((unused)), + grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { return GRUB_ERR_NOT_IMPLEMENTED_YET; diff --git a/disk/loopback.c b/disk/loopback.c index a19a83d56..a3b4c4a1f 100644 --- a/disk/loopback.c +++ b/disk/loopback.c @@ -1,7 +1,7 @@ /* loopback.c - command to add loopback devices. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005 Free Software Foundation, Inc. + * Copyright (C) 2005,2006 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 @@ -53,10 +53,12 @@ delete_loopback (const char *name) /* Search for the device. */ for (dev = loopback_list, prev = &loopback_list; - dev; prev = &dev->next, dev = dev->next) - if (!grub_strcmp (dev->devname, name)) + dev; + prev = &dev->next, dev = dev->next) + if (grub_strcmp (dev->devname, name) == 0) break; - if (!dev) + + if (! dev) return grub_error (GRUB_ERR_BAD_DEVICE, "Device not found"); /* Remove the device from the list. */ @@ -96,12 +98,13 @@ grub_cmd_loopback (struct grub_arg_list *state, /* First try to replace the old device. */ for (newdev = loopback_list; newdev; newdev = newdev->next) - if (!grub_strcmp (newdev->devname, args[0])) + if (grub_strcmp (newdev->devname, args[0]) == 0) break; + if (newdev) { char *newname = grub_strdup (args[1]); - if (!newname) + if (! newname) return grub_errno; grub_free (newdev->filename); @@ -115,18 +118,18 @@ grub_cmd_loopback (struct grub_arg_list *state, /* Unable to replace it, make a new entry. */ newdev = grub_malloc (sizeof (struct grub_loopback)); - if (!newdev) + if (! newdev) return grub_errno; newdev->devname = grub_strdup (args[0]); - if (!newdev->devname) + if (! newdev->devname) { grub_free (newdev); return grub_errno; } newdev->filename = grub_strdup (args[1]); - if (!newdev->devname) + if (! newdev->filename) { grub_free (newdev->devname); grub_free (newdev); @@ -163,7 +166,7 @@ grub_loopback_open (const char *name, grub_disk_t disk) struct grub_loopback *dev; for (dev = loopback_list; dev; dev = dev->next) - if (!grub_strcmp (dev->devname, name)) + if (grub_strcmp (dev->devname, name) == 0) break; if (! dev) @@ -193,26 +196,26 @@ grub_loopback_close (grub_disk_t disk) } static grub_err_t -grub_loopback_read (grub_disk_t disk, unsigned long sector, - unsigned long size, char *buf) +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; - long pos; + grub_off_t pos; - grub_file_seek (file, sector * GRUB_DISK_SECTOR_SIZE); + grub_file_seek (file, sector << GRUB_DISK_SECTOR_BITS); - grub_file_read (file, buf, size * GRUB_DISK_SECTOR_SIZE); + grub_file_read (file, buf, size << GRUB_DISK_SECTOR_BITS); if (grub_errno) return grub_errno; /* In case there is more data read than there is available, in case of files that are not a multiple of GRUB_DISK_SECTOR_SIZE, fill the rest with zeros. */ - pos = sector * GRUB_DISK_SECTOR_SIZE + size * GRUB_DISK_SECTOR_SIZE; + pos = (sector + size) << GRUB_DISK_SECTOR_BITS; if (pos > file->size) { - unsigned long amount = pos - file->size; - grub_memset (buf + pos - amount, amount, 0); + grub_size_t amount = pos - file->size; + grub_memset (buf + size - amount, 0, amount); } return 0; @@ -220,9 +223,9 @@ grub_loopback_read (grub_disk_t disk, unsigned long sector, static grub_err_t grub_loopback_write (grub_disk_t disk __attribute ((unused)), - unsigned long sector __attribute ((unused)), - unsigned long size __attribute ((unused)), - const char *buf __attribute ((unused))) + grub_disk_addr_t sector __attribute ((unused)), + grub_size_t size __attribute ((unused)), + const char *buf __attribute ((unused))) { return GRUB_ERR_NOT_IMPLEMENTED_YET; } @@ -243,7 +246,7 @@ static struct grub_disk_dev grub_loopback_dev = GRUB_MOD_INIT(loop) { - (void)mod; /* To stop warning. */ + (void) mod; /* To stop warning. */ grub_register_command ("loopback", grub_cmd_loopback, GRUB_COMMAND_FLAG_BOTH, "loopback [-d|-p] DEVICENAME FILE", "Make a device of a file.", options); @@ -255,4 +258,3 @@ GRUB_MOD_FINI(loop) grub_unregister_command ("loopback"); grub_disk_dev_unregister (&grub_loopback_dev); } - diff --git a/font/manager.c b/font/manager.c index 9b3dc91a5..8e53d9e50 100644 --- a/font/manager.c +++ b/font/manager.c @@ -207,7 +207,7 @@ grub_font_get_glyph (grub_uint32_t code, } if (bitmap - && (grub_file_read (font->file, bitmap, w * 16) + && (grub_file_read (font->file, (char *) bitmap, w * 16) != (grub_ssize_t) w * 16)) { remove_font (font); diff --git a/fs/affs.c b/fs/affs.c index 3350715bc..92a7b8c28 100644 --- a/fs/affs.c +++ b/fs/affs.c @@ -1,7 +1,7 @@ /* affs.c - Amiga Fast FileSystem. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005 Free Software Foundation, Inc. + * Copyright (C) 2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -150,9 +150,9 @@ grub_affs_read_block (grub_fshelp_node_t node, int fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_affs_read_file (grub_fshelp_node_t node, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf) + int pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_affs_read_block, @@ -439,7 +439,7 @@ grub_affs_close (grub_file_t file) /* Read LEN bytes data from FILE into BUF. */ static grub_ssize_t -grub_affs_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_affs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_affs_data *data = (struct grub_affs_data *) file->data; diff --git a/fs/ext2.c b/fs/ext2.c index 842e87a26..e69f2e0c2 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -241,7 +241,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, int fileblock) { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ext2fs doesn't support tripple indirect blocks"); - return grub_errno; + blknr = -1; } return blknr; @@ -252,9 +252,9 @@ grub_ext2_read_block (grub_fshelp_node_t node, int fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_ext2_read_file (grub_fshelp_node_t node, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf) + int pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_ext2_read_block, @@ -534,7 +534,7 @@ grub_ext2_close (grub_file_t file) /* Read LEN bytes data from FILE into BUF. */ static grub_ssize_t -grub_ext2_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_ext2_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_ext2_data *data = (struct grub_ext2_data *) file->data; diff --git a/fs/fat.c b/fs/fat.c index d4d2d388a..f2afae826 100644 --- a/fs/fat.c +++ b/fs/fat.c @@ -310,11 +310,11 @@ grub_fat_mount (grub_disk_t disk) static grub_ssize_t grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - grub_ssize_t offset, grub_ssize_t len, char *buf) + grub_off_t offset, grub_size_t len, char *buf) { - grub_ssize_t size; + grub_size_t size; grub_uint32_t logical_cluster; unsigned logical_cluster_bits; grub_ssize_t ret = 0; @@ -716,7 +716,7 @@ grub_fat_open (grub_file_t file, const char *name) } static grub_ssize_t -grub_fat_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_fat_read (grub_file_t file, char *buf, grub_size_t len) { return grub_fat_read_data (file->device->disk, file->data, file->read_hook, file->offset, len, buf); diff --git a/fs/fshelp.c b/fs/fshelp.c index 36619813d..832d68556 100644 --- a/fs/fshelp.c +++ b/fs/fshelp.c @@ -1,7 +1,7 @@ /* fshelp.c -- Filesystem helper functions */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2004,2005,2006 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 @@ -222,11 +222,11 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, blocks have a size of LOG2BLOCKSIZE (in log2). */ grub_ssize_t grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf, + int pos, grub_size_t len, char *buf, int (*get_block) (grub_fshelp_node_t node, int block), - unsigned int filesize, int log2blocksize) + grub_off_t filesize, int log2blocksize) { int i; int blockcnt; diff --git a/fs/hfs.c b/fs/hfs.c index 1b5f5a5a5..0a4a5d768 100644 --- a/fs/hfs.c +++ b/fs/hfs.c @@ -229,9 +229,9 @@ grub_hfs_block (struct grub_hfs_data *data, grub_hfs_datarecord_t dat, POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_hfs_read_file (struct grub_hfs_data *data, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf) + int pos, grub_size_t len, char *buf) { int i; int blockcnt; @@ -261,7 +261,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, blockend = (len + pos) % data->blksz; /* The last portion is exactly EXT2_BLOCK_SIZE (data). */ - if (!blockend) + if (! blockend) blockend = data->blksz; } @@ -804,7 +804,7 @@ grub_hfs_open (struct grub_file *file, const char *name) } static grub_ssize_t -grub_hfs_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_hfs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_hfs_data *data = (struct grub_hfs_data *) file->data; diff --git a/fs/hfsplus.c b/fs/hfsplus.c index cf9dbe5b8..6bd1c6d9d 100644 --- a/fs/hfsplus.c +++ b/fs/hfsplus.c @@ -357,9 +357,9 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, int fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_hfsplus_read_file (grub_fshelp_node_t node, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf) + int pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_hfsplus_read_block, @@ -865,7 +865,7 @@ grub_hfsplus_close (grub_file_t file) /* Read LEN bytes data from FILE into BUF. */ static grub_ssize_t -grub_hfsplus_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_hfsplus_data *data = (struct grub_hfsplus_data *) file->data; diff --git a/fs/iso9660.c b/fs/iso9660.c index 1b49c238c..225ce0df2 100644 --- a/fs/iso9660.c +++ b/fs/iso9660.c @@ -2,7 +2,7 @@ SUSP, Rock Ridge. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2004,2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -169,11 +169,11 @@ grub_iso9660_susp_iterate (struct grub_iso9660_data *data, ((char *) entry + entry->len)) { /* The last entry. */ - if (!grub_strncmp (entry->sig, "ST", 2)) + if (grub_strncmp ((char *) entry->sig, "ST", 2) == 0) break; /* Additional entries are stored elsewhere. */ - if (!grub_strncmp (entry->sig, "CE", 2)) + if (grub_strncmp ((char *) entry->sig, "CE", 2) == 0) { struct grub_iso9660_susp_ce *ce; @@ -215,7 +215,7 @@ grub_iso9660_mount (grub_disk_t disk) { /* The "ER" entry is used to detect extensions. The `IEEE_P1285' extension means Rock ridge. */ - if (!grub_strncmp (susp_entry->sig, "ER", 2)) + if (grub_strncmp ((char *) susp_entry->sig, "ER", 2) == 0) { data->rockridge = 1; return 1; @@ -224,7 +224,7 @@ grub_iso9660_mount (grub_disk_t disk) } data = grub_malloc (sizeof (struct grub_iso9660_data)); - if (!data) + if (! data) return 0; /* Read the superblock. */ @@ -236,7 +236,7 @@ grub_iso9660_mount (grub_disk_t disk) goto fail; } - if (grub_strncmp (data->voldesc.voldesc.magic, "CD001", 5)) + if (grub_strncmp ((char *) data->voldesc.voldesc.magic, "CD001", 5) == 0) { grub_error (GRUB_ERR_BAD_FS, "not a iso9660 filesystem"); goto fail; @@ -282,7 +282,7 @@ grub_iso9660_mount (grub_disk_t disk) entry = (struct grub_iso9660_susp_entry *) sua; /* Test if the SUSP protocol is used on this filesystem. */ - if (!grub_strncmp (entry->sig, "SP", 2)) + if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0) { /* The 2nd data byte stored how many bytes are skipped everytime to get to the SUA (System Usage Area). */ @@ -324,17 +324,16 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node) int size = grub_strlen (symlink); symlink = grub_realloc (symlink, size + len + 1); - if (!symlink) + if (! symlink) return; + grub_strncat (symlink, part, len); - - return; } /* Read in a symlink. */ grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *entry) { - if (!grub_strncmp ("SL", entry->sig, 2)) + if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0) { unsigned int pos = 1; @@ -355,7 +354,7 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node) /* The data on pos + 2 is the actual data, pos + 1 is the length. Both are part of the `Component Record'. */ - add_part (&entry->data[pos + 2], + add_part ((char *) &entry->data[pos + 2], entry->data[pos + 1]); if ((entry->data[pos] & 1)) addslash = 1; @@ -432,7 +431,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry) { /* The filename in the rock ridge entry. */ - if (!grub_strncmp ("NM", entry->sig, 2)) + if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0) { /* The flags are stored at the data position 0, here the filename type is stored. */ @@ -457,12 +456,12 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, filename[0] = '\0'; } filename_alloc = 1; - grub_strncpy (filename, &entry->data[1], size); - filename [size] = '\0'; + grub_strncpy (filename, (char *) &entry->data[1], size); + filename[size] = '\0'; } } /* The mode information (st_mode). */ - else if (!grub_strncmp (entry->sig, "PX", 2)) + else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0) { /* At position 0 of the PX record the st_mode information is stored. */ @@ -704,7 +703,7 @@ grub_iso9660_open (struct grub_file *file, const char *name) static grub_ssize_t -grub_iso9660_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_iso9660_data *data = (struct grub_iso9660_data *) file->data; @@ -742,7 +741,7 @@ grub_iso9660_label (grub_device_t device, char **label) if (data) { - *label = grub_strndup (data->voldesc.volname, 32); + *label = grub_strndup ((char *) data->voldesc.volname, 32); grub_free (data); } else diff --git a/fs/jfs.c b/fs/jfs.c index 9431f81a4..db54a0e10 100644 --- a/fs/jfs.c +++ b/fs/jfs.c @@ -1,7 +1,7 @@ /* jfs.c - JFS. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2004,2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -540,9 +540,9 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_jfs_read_file (struct grub_jfs_data *data, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf) + int pos, grub_size_t len, char *buf) { int i; int blockcnt; @@ -822,7 +822,7 @@ grub_jfs_open (struct grub_file *file, const char *name) static grub_ssize_t -grub_jfs_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_jfs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_jfs_data *data = (struct grub_jfs_data *) file->data; diff --git a/fs/minix.c b/fs/minix.c index e2112dd7b..7738a9d15 100644 --- a/fs/minix.c +++ b/fs/minix.c @@ -1,7 +1,7 @@ /* minix.c - The minix filesystem, version 1 and 2. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2004,2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -187,9 +187,9 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_minix_read_file (struct grub_minix_data *data, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf) + int pos, grub_disk_addr_t len, char *buf) { struct grub_minix_sblock *sblock = &data->sblock; int i; @@ -560,7 +560,7 @@ grub_minix_open (struct grub_file *file, const char *name) static grub_ssize_t -grub_minix_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_minix_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_minix_data *data = (struct grub_minix_data *) file->data; diff --git a/fs/sfs.c b/fs/sfs.c index 0d27b4385..6f708987d 100644 --- a/fs/sfs.c +++ b/fs/sfs.c @@ -1,7 +1,7 @@ /* sfs.c - Amiga Smart FileSystem. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005 Free Software Foundation, Inc. + * Copyright (C) 2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -259,9 +259,9 @@ grub_sfs_read_block (grub_fshelp_node_t node, int fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_sfs_read_file (grub_fshelp_node_t node, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf) + int pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_sfs_read_block, @@ -512,7 +512,7 @@ grub_sfs_close (grub_file_t file) /* Read LEN bytes data from FILE into BUF. */ static grub_ssize_t -grub_sfs_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_sfs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_sfs_data *data = (struct grub_sfs_data *) file->data; diff --git a/fs/ufs.c b/fs/ufs.c index 845374b8d..64226744b 100644 --- a/fs/ufs.c +++ b/fs/ufs.c @@ -241,9 +241,9 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, unsigned int blk) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_ufs_read_file (struct grub_ufs_data *data, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf) + int pos, grub_size_t len, char *buf) { struct grub_ufs_sblock *sblock = &data->sblock; int i; @@ -631,7 +631,7 @@ grub_ufs_open (struct grub_file *file, const char *name) static grub_ssize_t -grub_ufs_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_ufs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_ufs_data *data = (struct grub_ufs_data *) file->data; diff --git a/fs/xfs.c b/fs/xfs.c index 39adc204d..0d3b9bcba 100644 --- a/fs/xfs.c +++ b/fs/xfs.c @@ -1,7 +1,7 @@ /* xfs.c - XFS. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005 Free Software Foundation, Inc. + * Copyright (C) 2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -237,9 +237,9 @@ grub_xfs_read_block (grub_fshelp_node_t node, int fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_xfs_read_file (grub_fshelp_node_t node, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf) + int pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_xfs_read_block, @@ -628,7 +628,7 @@ grub_xfs_open (struct grub_file *file, const char *name) static grub_ssize_t -grub_xfs_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_xfs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_xfs_data *data = (struct grub_xfs_data *) file->data; diff --git a/include/grub/disk.h b/include/grub/disk.h index 62e981309..05974e02b 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -56,12 +56,12 @@ struct grub_disk_dev void (*close) (struct grub_disk *disk); /* Read SIZE sectors from the sector SECTOR of the disk DISK into BUF. */ - grub_err_t (*read) (struct grub_disk *disk, unsigned long sector, - unsigned long size, char *buf); + grub_err_t (*read) (struct grub_disk *disk, grub_disk_addr_t sector, + grub_size_t size, char *buf); /* Write SIZE sectors from BUF into the sector SECTOR of the disk DISK. */ - grub_err_t (*write) (struct grub_disk *disk, unsigned long sector, - unsigned long size, const char *buf); + grub_err_t (*write) (struct grub_disk *disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf); /* The next disk device. */ struct grub_disk_dev *next; @@ -80,7 +80,7 @@ struct grub_disk grub_disk_dev_t dev; /* The total number of sectors. */ - unsigned long total_sectors; + grub_uint64_t total_sectors; /* If partitions can be stored. */ int has_partitions; @@ -91,8 +91,10 @@ struct grub_disk /* The partition information. This is machine-specific. */ struct grub_partition *partition; - /* Called when a sector was read. */ - void (*read_hook) (unsigned long sector, unsigned offset, unsigned length); + /* Called when a sector was read. OFFSET is between 0 and + the sector size minus 1, and LENGTH is between 0 and the sector size. */ + void (*read_hook) (grub_disk_addr_t sector, + unsigned offset, unsigned length); /* Device-specific data. */ void *data; @@ -120,14 +122,14 @@ int EXPORT_FUNC(grub_disk_dev_iterate) (int (*hook) (const char *name)); grub_disk_t EXPORT_FUNC(grub_disk_open) (const char *name); void EXPORT_FUNC(grub_disk_close) (grub_disk_t disk); grub_err_t EXPORT_FUNC(grub_disk_read) (grub_disk_t disk, - unsigned long sector, - unsigned long offset, - unsigned long size, + grub_disk_addr_t sector, + grub_off_t offset, + grub_size_t size, char *buf); grub_err_t EXPORT_FUNC(grub_disk_write) (grub_disk_t disk, - unsigned long sector, - unsigned long offset, - unsigned long size, + grub_disk_addr_t sector, + grub_off_t offset, + grub_size_t size, const char *buf); diff --git a/include/grub/file.h b/include/grub/file.h index d5c85bc4a..5de948421 100644 --- a/include/grub/file.h +++ b/include/grub/file.h @@ -35,16 +35,17 @@ struct grub_file grub_fs_t fs; /* The current offset. */ - grub_ssize_t offset; + grub_off_t offset; /* The file size. */ - grub_ssize_t size; + grub_off_t size; /* Filesystem-specific data. */ void *data; /* This is called when a sector is read. Used only for a disk device. */ - void (*read_hook) (unsigned long sector, unsigned offset, unsigned length); + void (*read_hook) (grub_disk_addr_t sector, + unsigned offset, unsigned length); }; typedef struct grub_file *grub_file_t; @@ -53,18 +54,17 @@ char *EXPORT_FUNC(grub_file_get_device_name) (const char *name); grub_file_t EXPORT_FUNC(grub_file_open) (const char *name); grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, char *buf, - grub_ssize_t len); -grub_ssize_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, - grub_ssize_t offset); + grub_size_t len); +grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset); grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file); -static inline grub_ssize_t +static inline grub_off_t grub_file_size (const grub_file_t file) { return file->size; } -static inline grub_ssize_t +static inline grub_off_t grub_file_tell (const grub_file_t file) { return file->offset; diff --git a/include/grub/fs.h b/include/grub/fs.h index 4485cd382..e12a27c0e 100644 --- a/include/grub/fs.h +++ b/include/grub/fs.h @@ -42,7 +42,7 @@ struct grub_fs grub_err_t (*open) (struct grub_file *file, const char *name); /* Read LEN bytes data from FILE into BUF. */ - grub_ssize_t (*read) (struct grub_file *file, char *buf, grub_ssize_t len); + grub_ssize_t (*read) (struct grub_file *file, char *buf, grub_size_t len); /* Close the file FILE. */ grub_err_t (*close) (struct grub_file *file); diff --git a/include/grub/fshelp.h b/include/grub/fshelp.h index 2924d7ef5..36de779ae 100644 --- a/include/grub/fshelp.h +++ b/include/grub/fshelp.h @@ -1,7 +1,7 @@ /* fshelp.h -- Filesystem helper functions */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2004,2005,2006 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 @@ -64,13 +64,13 @@ EXPORT_FUNC(grub_fshelp_find_file) (const char *path, blocks have a size of LOG2BLOCKSIZE (in log2). */ grub_ssize_t EXPORT_FUNC(grub_fshelp_read_file) (grub_disk_t disk, grub_fshelp_node_t node, - void (*read_hook) (unsigned long sector, + void (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, unsigned int len, char *buf, + int pos, grub_size_t len, char *buf, int (*get_block) (grub_fshelp_node_t node, int block), - unsigned int filesize, int log2blocksize); + grub_off_t filesize, int log2blocksize); unsigned int EXPORT_FUNC(grub_fshelp_log2blksize) (unsigned int blksize, diff --git a/include/grub/i386/pc/boot.h b/include/grub/i386/pc/boot.h index 047cf38a6..22374a82d 100644 --- a/include/grub/i386/pc/boot.h +++ b/include/grub/i386/pc/boot.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2002,2005 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2002,2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,22 +33,19 @@ #define GRUB_BOOT_MACHINE_VER_MAJ 0x3e /* The offset of BOOT_DRIVE. */ -#define GRUB_BOOT_MACHINE_BOOT_DRIVE 0x40 - -/* The offset of FORCE_LBA. */ -#define GRUB_BOOT_MACHINE_FORCE_LBA 0x41 +#define GRUB_BOOT_MACHINE_BOOT_DRIVE 0x4c /* The offset of KERNEL_ADDRESS. */ -#define GRUB_BOOT_MACHINE_KERNEL_ADDRESS 0x42 +#define GRUB_BOOT_MACHINE_KERNEL_ADDRESS 0x40 /* The offset of KERNEL_SECTOR. */ #define GRUB_BOOT_MACHINE_KERNEL_SECTOR 0x44 /* The offset of KERNEL_SEGMENT. */ -#define GRUB_BOOT_MACHINE_KERNEL_SEGMENT 0x48 +#define GRUB_BOOT_MACHINE_KERNEL_SEGMENT 0x42 /* The offset of BOOT_DRIVE_CHECK. */ -#define GRUB_BOOT_MACHINE_DRIVE_CHECK 0x4b +#define GRUB_BOOT_MACHINE_DRIVE_CHECK 0x4e /* The offset of a magic number used by Windows NT. */ #define GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC 0x1b8 @@ -77,6 +74,6 @@ #define GRUB_BOOT_MACHINE_KERNEL_ADDR (GRUB_BOOT_MACHINE_KERNEL_SEG << 4) /* The size of a block list used in the kernel startup code. */ -#define GRUB_BOOT_MACHINE_LIST_SIZE 8 +#define GRUB_BOOT_MACHINE_LIST_SIZE 12 #endif /* ! BOOT_MACHINE_HEADER */ diff --git a/include/grub/misc.h b/include/grub/misc.h index 3a945d8dd..35f7507a2 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -56,6 +56,7 @@ int EXPORT_FUNC(grub_isgraph) (int c); int EXPORT_FUNC(grub_isdigit) (int c); int EXPORT_FUNC(grub_tolower) (int c); unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int base); +unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, int base); char *EXPORT_FUNC(grub_strdup) (const char *s); char *EXPORT_FUNC(grub_strndup) (const char *s, grub_size_t n); void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n); @@ -76,6 +77,8 @@ grub_uint8_t *EXPORT_FUNC(grub_utf16_to_utf8) (grub_uint8_t *dest, grub_ssize_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest, const grub_uint8_t *src, grub_size_t size); +grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, + grub_uint32_t d, grub_uint32_t *r); /* Inline functions. */ static inline unsigned int diff --git a/include/grub/partition.h b/include/grub/partition.h index 92f533704..9b95753bc 100644 --- a/include/grub/partition.h +++ b/include/grub/partition.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2004,2006 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 @@ -34,7 +34,8 @@ struct grub_partition_map /* Call HOOK with each partition, until HOOK returns non-zero. */ grub_err_t (*iterate) (struct grub_disk *disk, - int (*hook) (struct grub_disk *disk, const grub_partition_t partition)); + int (*hook) (struct grub_disk *disk, + const grub_partition_t partition)); /* Return the partition named STR on the disk DISK. */ grub_partition_t (*probe) (struct grub_disk *disk, @@ -52,13 +53,13 @@ typedef struct grub_partition_map *grub_partition_map_t; struct grub_partition { /* The start sector. */ - unsigned long start; + grub_disk_addr_t start; /* The length in sector units. */ - unsigned long len; + grub_uint64_t len; /* The offset of the partition table. */ - unsigned long offset; + grub_disk_addr_t offset; /* The index of this partition in the partition table. */ int index; @@ -94,13 +95,13 @@ void grub_sun_partition_map_init (void); void grub_sun_partition_map_fini (void); #endif -static inline unsigned long +static inline grub_disk_addr_t grub_partition_get_start (const grub_partition_t p) { return p->start; } -static inline unsigned long +static inline grub_uint64_t grub_partition_get_len (const grub_partition_t p) { return p->len; diff --git a/include/grub/types.h b/include/grub/types.h index cb07f2aa8..40d9b7d69 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -83,18 +83,19 @@ typedef grub_int32_t grub_host_ssize_t; #if GRUB_CPU_SIZEOF_VOID_P == 8 typedef grub_uint64_t grub_addr_t; -typedef grub_uint64_t grub_off_t; typedef grub_uint64_t grub_size_t; typedef grub_int64_t grub_ssize_t; #else typedef grub_uint32_t grub_addr_t; -typedef grub_uint32_t grub_off_t; typedef grub_uint32_t grub_size_t; typedef grub_int32_t grub_ssize_t; #endif -/* FIXME: Will be grub_uint64_t */ -typedef unsigned long grub_disk_addr_t; +/* The type for representing a file offset. */ +typedef grub_uint64_t grub_off_t; + +/* The type for representing a disk block address. */ +typedef grub_uint64_t grub_disk_addr_t; /* Byte-orders. */ #define grub_swap_bytes16(x) \ diff --git a/io/gzio.c b/io/gzio.c index 6bb59b800..08bd8de97 100644 --- a/io/gzio.c +++ b/io/gzio.c @@ -1,7 +1,7 @@ /* gzio.c - decompression support for gzip */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2005 Free Software Foundation, Inc. + * Copyright (C) 1999,2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -60,7 +60,7 @@ struct grub_gzio /* The underlyding file object. */ grub_file_t file; /* The offset at which the data starts in the underlyding file. */ - grub_ssize_t data_offset; + grub_off_t data_offset; /* The type of current block. */ int block_type; /* The length of current block. */ @@ -93,7 +93,7 @@ struct grub_gzio /* The lookup bits for the distance code table. */ int bd; /* The original offset value. */ - grub_ssize_t saved_offset; + grub_off_t saved_offset; }; typedef struct grub_gzio *grub_gzio_t; @@ -176,7 +176,7 @@ test_header (grub_file_t file) * (other than a real error with the disk) then we don't think it * is a compressed file, and simply mark it as such. */ - if (grub_file_read (gzio->file, buf, 10) != 10 + if (grub_file_read (gzio->file, (char *) buf, 10) != 10 || ((*((grub_uint16_t *) buf) != GZIP_MAGIC) && (*((grub_uint16_t *) buf) != OLD_GZIP_MAGIC))) { @@ -192,7 +192,7 @@ test_header (grub_file_t file) if (buf[2] != DEFLATED || (buf[3] & UNSUPPORTED_FLAGS) || ((buf[3] & EXTRA_FIELD) - && (grub_file_read (gzio->file, buf, 2) != 2 + && (grub_file_read (gzio->file, (char *) buf, 2) != 2 || eat_field (gzio->file, grub_le_to_cpu16 (*((grub_uint16_t *) buf))))) || ((buf[3] & ORIG_NAME) && eat_field (gzio->file, -1)) @@ -206,12 +206,14 @@ test_header (grub_file_t file) grub_file_seek (gzio->file, grub_file_size (gzio->file) - 8); - if (grub_file_read (gzio->file, buf, 8) != 8) + if (grub_file_read (gzio->file, (char *) buf, 8) != 8) { grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format"); return 0; } + /* FIXME: this does not handle files whose original size is over 4GB. + But how can we know the real original size? */ file->size = grub_le_to_cpu32 (*((grub_uint32_t *) (buf + 4))); initialize_tables (file); @@ -362,11 +364,11 @@ get_byte (grub_file_t file) { grub_gzio_t gzio = file->data; - if (grub_file_tell (gzio->file) == gzio->data_offset + if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset || gzio->inbuf_d == INBUFSIZ) { gzio->inbuf_d = 0; - grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ); + grub_file_read (gzio->file, (char *) gzio->inbuf, INBUFSIZ); } return gzio->inbuf[gzio->inbuf_d++]; @@ -1166,11 +1168,11 @@ grub_gzfile_open (const char *name, int transparent) } static grub_ssize_t -grub_gzio_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_gzio_read (grub_file_t file, char *buf, grub_size_t len) { grub_ssize_t ret = 0; grub_gzio_t gzio = file->data; - grub_ssize_t offset; + grub_off_t offset; /* Do we reset decompression to the beginning of the file? */ if (gzio->saved_offset > file->offset + WSIZE) @@ -1186,7 +1188,7 @@ grub_gzio_read (grub_file_t file, char *buf, grub_ssize_t len) while (len > 0 && grub_errno == GRUB_ERR_NONE) { - register grub_ssize_t size; + register grub_size_t size; register char *srcaddr; while (offset >= gzio->saved_offset) diff --git a/kern/disk.c b/kern/disk.c index ecd0b7b1d..5ae8d78b3 100644 --- a/kern/disk.c +++ b/kern/disk.c @@ -37,7 +37,7 @@ struct grub_disk_cache { unsigned long dev_id; unsigned long disk_id; - unsigned long sector; + grub_disk_addr_t sector; char *data; int lock; }; @@ -58,16 +58,16 @@ grub_disk_cache_get_performance (unsigned long *hits, unsigned long *misses) static unsigned grub_disk_cache_get_index (unsigned long dev_id, unsigned long disk_id, - unsigned long sector) + grub_disk_addr_t sector) { return ((dev_id * 524287UL + disk_id * 2606459UL - + (sector >> GRUB_DISK_CACHE_BITS)) + + ((unsigned) (sector >> GRUB_DISK_CACHE_BITS))) % GRUB_DISK_CACHE_NUM); } static void grub_disk_cache_invalidate (unsigned long dev_id, unsigned long disk_id, - unsigned long sector) + grub_disk_addr_t sector) { unsigned index; struct grub_disk_cache *cache; @@ -105,7 +105,7 @@ grub_disk_cache_invalidate_all (void) static char * grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id, - unsigned long sector) + grub_disk_addr_t sector) { struct grub_disk_cache *cache; unsigned index; @@ -132,7 +132,7 @@ grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id, static void grub_disk_cache_unlock (unsigned long dev_id, unsigned long disk_id, - unsigned long sector) + grub_disk_addr_t sector) { struct grub_disk_cache *cache; unsigned index; @@ -147,7 +147,7 @@ grub_disk_cache_unlock (unsigned long dev_id, unsigned long disk_id, static grub_err_t grub_disk_cache_store (unsigned long dev_id, unsigned long disk_id, - unsigned long sector, const char *data) + grub_disk_addr_t sector, const char *data) { unsigned index; struct grub_disk_cache *cache; @@ -306,15 +306,16 @@ grub_disk_close (grub_disk_t disk) } static grub_err_t -grub_disk_check_range (grub_disk_t disk, unsigned long *sector, - unsigned long *offset, grub_ssize_t size) +grub_disk_check_range (grub_disk_t disk, grub_disk_addr_t *sector, + grub_off_t *offset, grub_size_t size) { *sector += *offset >> GRUB_DISK_SECTOR_BITS; *offset &= GRUB_DISK_SECTOR_SIZE - 1; if (disk->partition) { - unsigned long start, len; + grub_disk_addr_t start; + grub_uint64_t len; start = grub_partition_get_start (disk->partition); len = grub_partition_get_len (disk->partition); @@ -337,15 +338,18 @@ grub_disk_check_range (grub_disk_t disk, unsigned long *sector, /* Read data from the disk. */ grub_err_t -grub_disk_read (grub_disk_t disk, unsigned long sector, - unsigned long offset, unsigned long size, char *buf) +grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, char *buf) { char *tmp_buf; - + unsigned real_offset; + /* First of all, check if the region is within the disk. */ if (grub_disk_check_range (disk, §or, &offset, size) != GRUB_ERR_NONE) return grub_errno; + real_offset = offset; + /* Allocate a temporary buffer. */ tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS); if (! tmp_buf) @@ -355,14 +359,15 @@ grub_disk_read (grub_disk_t disk, unsigned long sector, while (size) { char *data; - unsigned long start_sector; - unsigned long len; - unsigned long pos; + grub_disk_addr_t start_sector; + grub_size_t len; + grub_size_t pos; /* For reading bulk data. */ start_sector = sector & ~(GRUB_DISK_CACHE_SIZE - 1); pos = (sector - start_sector) << GRUB_DISK_SECTOR_BITS; - len = (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS) - pos - offset; + len = ((GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS) + - pos - real_offset); if (len > size) len = size; @@ -371,7 +376,7 @@ grub_disk_read (grub_disk_t disk, unsigned long sector, if (data) { /* Just copy it! */ - grub_memcpy (buf, data + pos + offset, len); + grub_memcpy (buf, data + pos + real_offset, len); grub_disk_cache_unlock (disk->dev->id, disk->id, start_sector); } else @@ -396,19 +401,19 @@ grub_disk_read (grub_disk_t disk, unsigned long sector, if ((disk->dev->read) (disk, sector, num, tmp_buf)) goto finish; - grub_memcpy (buf, tmp_buf + offset, size); + grub_memcpy (buf, tmp_buf + real_offset, size); /* Call the read hook, if any. */ if (disk->read_hook) while (size) { - (disk->read_hook) (sector, offset, + (disk->read_hook) (sector, real_offset, ((size > GRUB_DISK_SECTOR_SIZE) ? GRUB_DISK_SECTOR_SIZE : size)); sector++; - size -= GRUB_DISK_SECTOR_SIZE - offset; - offset = 0; + size -= GRUB_DISK_SECTOR_SIZE - real_offset; + real_offset = 0; } /* This must be the end. */ @@ -416,7 +421,7 @@ grub_disk_read (grub_disk_t disk, unsigned long sector, } /* Copy it and store it in the disk cache. */ - grub_memcpy (buf, tmp_buf + pos + offset, len); + grub_memcpy (buf, tmp_buf + pos + real_offset, len); grub_disk_cache_store (disk->dev->id, disk->id, start_sector, tmp_buf); } @@ -424,29 +429,29 @@ grub_disk_read (grub_disk_t disk, unsigned long sector, /* Call the read hook, if any. */ if (disk->read_hook) { - unsigned long s = sector; - unsigned long l = len; + grub_disk_addr_t s = sector; + grub_size_t l = len; while (l) { - (disk->read_hook) (s, offset, + (disk->read_hook) (s, real_offset, ((l > GRUB_DISK_SECTOR_SIZE) ? GRUB_DISK_SECTOR_SIZE : l)); - if (l < GRUB_DISK_SECTOR_SIZE - offset) + if (l < GRUB_DISK_SECTOR_SIZE - real_offset) break; s++; - l -= GRUB_DISK_SECTOR_SIZE - offset; - offset = 0; + l -= GRUB_DISK_SECTOR_SIZE - real_offset; + real_offset = 0; } } sector = start_sector + GRUB_DISK_CACHE_SIZE; buf += len; size -= len; - offset = 0; + real_offset = 0; } finish: @@ -457,28 +462,32 @@ grub_disk_read (grub_disk_t disk, unsigned long sector, } grub_err_t -grub_disk_write (grub_disk_t disk, unsigned long sector, - unsigned long offset, unsigned long size, const char *buf) +grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, const char *buf) { + unsigned real_offset; + if (grub_disk_check_range (disk, §or, &offset, size) != GRUB_ERR_NONE) return -1; + real_offset = offset; + while (size) { - if (offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0)) + if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0)) { char tmp_buf[GRUB_DISK_SECTOR_SIZE]; - unsigned long len; + grub_size_t len; if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf) != GRUB_ERR_NONE) goto finish; - len = GRUB_DISK_SECTOR_SIZE - offset; + len = GRUB_DISK_SECTOR_SIZE - real_offset; if (len > size) len = size; - grub_memcpy (tmp_buf + offset, buf, len); + grub_memcpy (tmp_buf + real_offset, buf, len); grub_disk_cache_invalidate (disk->dev->id, disk->id, sector); @@ -488,12 +497,12 @@ grub_disk_write (grub_disk_t disk, unsigned long sector, sector++; buf += len; size -= len; - offset = 0; + real_offset = 0; } else { - unsigned long len; - unsigned long n; + grub_size_t len; + grub_size_t n; len = size & ~(GRUB_DISK_SECTOR_SIZE - 1); n = size >> GRUB_DISK_SECTOR_BITS; diff --git a/kern/file.c b/kern/file.c index 4ffbe5c23..846914814 100644 --- a/kern/file.c +++ b/kern/file.c @@ -1,7 +1,7 @@ /* file.c - file I/O functions */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002,2006 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 @@ -112,13 +112,17 @@ grub_file_open (const char *name) } grub_ssize_t -grub_file_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_file_read (grub_file_t file, char *buf, grub_size_t len) { grub_ssize_t res; if (len == 0 || len > file->size - file->offset) len = file->size - file->offset; + /* Prevent an overflow. */ + if ((grub_ssize_t) len < 0) + len >>= 1; + if (len == 0) return 0; @@ -141,12 +145,12 @@ grub_file_close (grub_file_t file) return grub_errno; } -grub_ssize_t -grub_file_seek (grub_file_t file, grub_ssize_t offset) +grub_off_t +grub_file_seek (grub_file_t file, grub_off_t offset) { - grub_ssize_t old; + grub_off_t old; - if (offset < 0 || offset > file->size) + if (offset > file->size) { grub_error (GRUB_ERR_OUT_OF_RANGE, "attempt to seek outside of the file"); diff --git a/kern/fs.c b/kern/fs.c index 91aba7c02..2ef314510 100644 --- a/kern/fs.c +++ b/kern/fs.c @@ -132,7 +132,7 @@ grub_fs_probe (grub_device_t device) struct grub_fs_block { - unsigned long offset; + grub_disk_addr_t offset; unsigned long length; }; @@ -150,6 +150,8 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) { num++; p = grub_strchr (p, ','); + if (p) + p++; } while (p); @@ -164,7 +166,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) { if (*p != '+') { - blocks[i].offset = grub_strtoul (p, &p, 0); + blocks[i].offset = grub_strtoull (p, &p, 0); if (grub_errno != GRUB_ERR_NONE || *p != '+') { grub_error (GRUB_ERR_BAD_FILENAME, @@ -207,11 +209,11 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) } static grub_ssize_t -grub_fs_blocklist_read (grub_file_t file, char *buf, grub_ssize_t len) +grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_fs_block *p; - unsigned long sector; - unsigned long offset; + grub_disk_addr_t sector; + grub_off_t offset; grub_ssize_t ret = 0; if (len > file->size - file->offset) @@ -223,7 +225,7 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_ssize_t len) { if (sector < p->length) { - grub_ssize_t size; + grub_size_t size; size = len; if (((size + offset + GRUB_DISK_SECTOR_SIZE - 1) diff --git a/kern/misc.c b/kern/misc.c index 2ec65e0ea..cbf1560a3 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -338,10 +338,26 @@ grub_tolower (int c) return c; } + unsigned long grub_strtoul (const char *str, char **end, int base) { - unsigned long num = 0; + unsigned long long num; + + num = grub_strtoull (str, end, base); + if (num > ~0UL) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected"); + return ~0UL; + } + + return (unsigned long) num; +} + +unsigned long long +grub_strtoull (const char *str, char **end, int base) +{ + unsigned long long num = 0; int found = 0; /* Skip white spaces. */ @@ -380,11 +396,12 @@ grub_strtoul (const char *str, char **end, int base) } found = 1; - - if (num > (~0UL - digit) / base) + + /* NUM * BASE + DIGIT > ~0ULL */ + if (num > grub_divmod64 (~0ULL - digit, base, 0)) { grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected"); - return 0; + return ~0ULL; } num = num * base + digit; @@ -501,6 +518,50 @@ grub_itoa (char *str, int c, unsigned n) return p; } +/* 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) +{ + /* 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 + represents the high 64 bits in 128-bits space. */ + unsigned bits = 64; + unsigned long long q = 0; + unsigned m = 0; + + /* Skip the slow computation, if 32-bit arithmetics are possible. */ + if (n < 0xffffffff) + { + if (r) + *r = ((grub_uint32_t) n) % d; + + return ((grub_uint32_t) n) / d; + } + + while (bits--) + { + m <<= 1; + + if (n & (1ULL << 63)) + m |= 1; + + q <<= 1; + n <<= 1; + + if (m >= d) + { + q |= 1; + m -= d; + } + } + + if (r) + *r = m; + + return q; +} + /* Convert a long long value to a string. This function avoids 64-bit modular arithmetic or divisions. */ static char * @@ -528,33 +589,10 @@ grub_lltoa (char *str, int c, unsigned long long n) /* BASE == 10 */ do { - /* 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 - represents the high 64 bits in 128-bits space. */ - unsigned bits = sizeof (unsigned long long) * 8; - unsigned long long q = 0; - unsigned m = 0; - - while (bits--) - { - m <<= 1; - - if ((long long ) n < 0) - m |= 1; - - q <<= 1; - n <<= 1; - - if (m >= 10) - { - q |= 1; - m -= 10; - } - } - + unsigned m; + + n = grub_divmod64 (n, 10, &m); *p++ = m + '0'; - n = q; } while (n); diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c index 82dc428f1..6709ae470 100644 --- a/loader/i386/pc/multiboot.c +++ b/loader/i386/pc/multiboot.c @@ -127,7 +127,8 @@ grub_multiboot_load_elf32 (grub_file_t file, void *buffer) return grub_error (GRUB_ERR_BAD_OS, "segment doesn't fit in memory reserved for the OS"); - if (grub_file_seek (file, phdr->p_offset) == -1) + if (grub_file_seek (file, (grub_off_t) phdr->p_offset) + == (grub_off_t) -1) return grub_error (GRUB_ERR_BAD_OS, "invalid offset in program header"); @@ -201,7 +202,8 @@ grub_multiboot_load_elf64 (grub_file_t file, void *buffer) return grub_error (GRUB_ERR_BAD_OS, "segment doesn't fit in memory reserved for the OS"); - if (grub_file_seek (file, phdr->p_offset) == -1) + if (grub_file_seek (file, (grub_off_t) phdr->p_offset) + == (grub_off_t) -1) return grub_error (GRUB_ERR_BAD_OS, "invalid offset in program header"); diff --git a/normal/lexer.c b/normal/lexer.c index fbab1ca84..e14a9cae6 100644 --- a/normal/lexer.c +++ b/normal/lexer.c @@ -357,7 +357,8 @@ grub_script_yylex2 (YYSTYPE *yylval, struct grub_parser_param *parsestate) } void -grub_script_yyerror (struct grub_parser_param *lex, char const *err) +grub_script_yyerror (struct grub_parser_param *lex __attribute__ ((unused)), + char const *err) { grub_printf ("%s\n", err); } diff --git a/normal/parser.y b/normal/parser.y index 6948beff0..ca6aba9dc 100644 --- a/normal/parser.y +++ b/normal/parser.y @@ -24,7 +24,7 @@ #define YYFREE grub_free #define YYMALLOC grub_malloc - +#define YYLTYPE_IS_TRIVIAL 0 %} diff --git a/normal/script.c b/normal/script.c index 033ab976b..dc4c2f12a 100644 --- a/normal/script.c +++ b/normal/script.c @@ -292,7 +292,6 @@ struct grub_script * grub_script_parse (char *script, grub_err_t (*getline) (char **)) { struct grub_script *parsed; - struct grub_script_mem *memfree; struct grub_script_mem *membackup; struct grub_lexer_param *lexstate; struct grub_parser_param *parsestate; diff --git a/partmap/amiga.c b/partmap/amiga.c index 98d67a717..bb5417ff5 100644 --- a/partmap/amiga.c +++ b/partmap/amiga.c @@ -1,7 +1,7 @@ /* amiga.c - Read amiga partition tables (RDB). */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2002,2004,2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -98,7 +98,7 @@ amiga_partition_map_iterate (grub_disk_t disk, sizeof (rdsk), (char *) &rdsk)) return grub_errno; - if (!grub_strcmp (rdsk.magic, "RDSK")) + if (grub_strcmp ((char *) rdsk.magic, "RDSK") == 0) { /* Found the first PART block. */ next = grub_be_to_cpu32 (rdsk.partitionlst); diff --git a/partmap/gpt.c b/partmap/gpt.c index 7106ae7ca..cfcb974c9 100644 --- a/partmap/gpt.c +++ b/partmap/gpt.c @@ -1,7 +1,7 @@ /* gpt.c - Read GUID Partition Tables (GPT). */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002, 2005 Free Software Foundation, Inc. + * Copyright (C) 2002,2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -126,7 +126,7 @@ gpt_partition_map_iterate (grub_disk_t disk, part.index = partno; part.partmap = &grub_gpt_partition_map; - grub_dprintf ("gpt", "GPT entry %d: start=%ld, length=%ld\n", + grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", partno, part.start, part.len); if (hook (disk, &part)) diff --git a/partmap/pc.c b/partmap/pc.c index 3d2d8ad12..7aee7ec93 100644 --- a/partmap/pc.c +++ b/partmap/pc.c @@ -1,7 +1,7 @@ /* pc.c - Read PC style partition tables. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2004,2005 Free Software Foundation, Inc. + * Copyright (C) 2002,2004,2005,2006 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 @@ -137,7 +137,7 @@ pc_partition_map_iterate (grub_disk_t disk, pcdata.bsd_type = -1; grub_dprintf ("partition", - "partition %d: flag 0x%x, type 0x%x, start 0x%lx, len 0x%lx\n", + "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n", p.index, e->flag, pcdata.dos_type, p.start, p.len); /* If this is a GPT partition, this MBR is just a dummy. */ diff --git a/util/i386/pc/biosdisk.c b/util/i386/pc/biosdisk.c index b2d317fd3..2459999ec 100644 --- a/util/i386/pc/biosdisk.c +++ b/util/i386/pc/biosdisk.c @@ -1,7 +1,7 @@ /* biosdisk.c - emulate biosdisk */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2006 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 @@ -285,7 +285,7 @@ linux_find_partition (char *dev, unsigned long sector) #endif /* __linux__ */ static int -open_device (const grub_disk_t disk, unsigned long sector, int flags) +open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) { int fd; @@ -421,8 +421,8 @@ nwrite (int fd, const char *buf, size_t len) } static grub_err_t -grub_util_biosdisk_read (grub_disk_t disk, unsigned long sector, - unsigned long size, char *buf) +grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) { int fd; @@ -458,8 +458,8 @@ grub_util_biosdisk_read (grub_disk_t disk, unsigned long sector, } static grub_err_t -grub_util_biosdisk_write (grub_disk_t disk, unsigned long sector, - unsigned long size, const char *buf) +grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) { int fd; diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index bee086679..e128fb0f2 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -60,7 +60,7 @@ /* This is the blocklist used in the diskboot image. */ struct boot_blocklist { - grub_uint32_t start; + grub_uint64_t start; grub_uint16_t len; grub_uint16_t segment; } __attribute__ ((packed)); @@ -99,14 +99,14 @@ setup (const char *prefix, const char *dir, grub_uint16_t core_sectors; grub_device_t root_dev, dest_dev; grub_uint8_t *boot_drive; - grub_uint32_t *kernel_sector; + grub_disk_addr_t *kernel_sector; grub_uint16_t *boot_drive_check; struct boot_blocklist *first_block, *block; grub_int32_t *install_dos_part, *install_bsd_part; char *install_prefix; char *tmp_img; int i; - unsigned long first_sector; + grub_disk_addr_t first_sector; grub_uint16_t current_segment = GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4); grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; @@ -114,9 +114,9 @@ setup (const char *prefix, const char *dir, FILE *fp; unsigned long first_start = ~0UL; - auto void save_first_sector (unsigned long sector, unsigned offset, + auto void save_first_sector (grub_disk_addr_t sector, unsigned offset, unsigned length); - auto void save_blocklists (unsigned long sector, unsigned offset, + auto void save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length); auto int find_first_partition_start (grub_disk_t disk, @@ -135,10 +135,10 @@ setup (const char *prefix, const char *dir, return 0; } - void save_first_sector (unsigned long sector, unsigned offset, + void save_first_sector (grub_disk_addr_t sector, unsigned offset, unsigned length) { - grub_util_info ("the fist sector is <%lu,%u,%u>", + grub_util_info ("the first sector is <%llu,%u,%u>", sector, offset, length); if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) @@ -147,23 +147,24 @@ setup (const char *prefix, const char *dir, first_sector = sector; } - void save_blocklists (unsigned long sector, unsigned offset, unsigned length) + void save_blocklists (grub_disk_addr_t sector, unsigned offset, + unsigned length) { struct boot_blocklist *prev = block + 1; - grub_util_info ("saving <%lu,%u,%u> with the segment 0x%x", + grub_util_info ("saving <%llu,%u,%u> with the segment 0x%x", sector, offset, length, (unsigned) current_segment); if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) grub_util_error ("Non-sector-aligned data is found in the core file"); if (block != first_block - && (grub_le_to_cpu32 (prev->start) + && (grub_le_to_cpu64 (prev->start) + grub_le_to_cpu16 (prev->len)) == sector) prev->len = grub_cpu_to_le16 (grub_le_to_cpu16 (prev->len) + 1); else { - block->start = grub_cpu_to_le32 (sector); + block->start = grub_cpu_to_le64 (sector); block->len = grub_cpu_to_le16 (1); block->segment = grub_cpu_to_le16 (current_segment); @@ -187,7 +188,7 @@ setup (const char *prefix, const char *dir, /* Set the addresses of BOOT_DRIVE, KERNEL_SECTOR and BOOT_DRIVE_CHECK. */ boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); - kernel_sector = (grub_uint32_t *) (boot_img + kernel_sector = (grub_disk_addr_t *) (boot_img + GRUB_BOOT_MACHINE_KERNEL_SECTOR); boot_drive_check = (grub_uint16_t *) (boot_img + GRUB_BOOT_MACHINE_DRIVE_CHECK); @@ -266,7 +267,7 @@ setup (const char *prefix, const char *dir, grub_util_info ("will embed the core image into after the MBR"); /* The first blocklist contains the whole sectors. */ - first_block->start = grub_cpu_to_le32 (2); + first_block->start = grub_cpu_to_le64 (2); first_block->len = grub_cpu_to_le16 (core_sectors - 1); first_block->segment = grub_cpu_to_le16 (GRUB_BOOT_MACHINE_KERNEL_SEG @@ -305,7 +306,7 @@ setup (const char *prefix, const char *dir, /* The boot image and the core image are on the same drive, so there is no need to specify the boot drive explicitly. */ *boot_drive = 0xff; - *kernel_sector = grub_cpu_to_le32 (1); + *kernel_sector = grub_cpu_to_le64 (1); /* Write the boot image onto the disk. */ if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, @@ -339,7 +340,7 @@ setup (const char *prefix, const char *dir, file = grub_file_open (core_path); if (file) { - if (grub_file_size (file) != (grub_ssize_t) core_size) + if (grub_file_size (file) != core_size) grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", (int) grub_file_size (file), (int) core_size); else if (grub_file_read (file, tmp_img, core_size) @@ -424,7 +425,7 @@ setup (const char *prefix, const char *dir, free (core_path); free (tmp_img); - *kernel_sector = grub_cpu_to_le32 (first_sector); + *kernel_sector = grub_cpu_to_le64 (first_sector); /* If the destination device is different from the root device, it is necessary to embed the boot drive explicitly. */