merge mainline into ehci

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2012-02-01 13:19:42 +01:00
commit cefa01261b
443 changed files with 38931 additions and 11122 deletions

View file

@ -78,13 +78,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
if COND_i386_pc
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h

View file

@ -18,6 +18,18 @@ script = {
common = modinfo.sh.in;
};
script = {
installdir = noinst;
name = gmodule.pl;
common = gmodule.pl.in;
};
script = {
installdir = noinst;
name = gdb_grub;
common = gdb_grub.in;
};
kernel = {
name = kernel;
@ -34,7 +46,7 @@ kernel = {
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
@ -101,7 +113,7 @@ kernel = {
ieee1275 = kern/ieee1275/ieee1275.c;
ieee1275 = kern/ieee1275/mmap.c;
ieee1275 = kern/ieee1275/openfw.c;
ieee1275 = term/ieee1275/ofconsole.c;
ieee1275 = term/ieee1275/console.c;
ieee1275 = kern/ieee1275/init.c;
terminfoinkernel = term/terminfo.c;
@ -356,6 +368,15 @@ image = {
enable = mips;
};
image = {
name = lzma_decompress;
i386_pc = boot/i386/pc/startup_raw.S;
objcopyflags = '-O binary';
ldflags = '$(TARGET_IMG_LDFLAGS) -Wl,-Ttext,0x8200';
enable = i386_pc;
};
image = {
name = fwstart;
mips_loongson = boot/mips/loongson/fwstart.S;
@ -400,11 +421,15 @@ module = {
module = {
name = usb;
common = bus/usb/usb.c;
noemu = bus/usb/usbtrans.c;
noemu = bus/usb/usbhub.c;
enable = emu;
common = bus/usb/usbtrans.c;
common = bus/usb/usbhub.c;
enable = usb;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
name = emuusb;
common = bus/usb/usb.c;
condition = COND_GRUB_EMU_USB;
};
module = {
@ -445,18 +470,22 @@ module = {
module = {
name = pci;
noemu = bus/pci.c;
emu = bus/emu/pci.c;
emu = commands/lspci.c;
common = bus/pci.c;
enable = emu;
enable = i386_pc;
enable = i386_efi;
enable = x86_64_efi;
enable = i386_ieee1275;
enable = i386_coreboot;
enable = i386_multiboot;
emu_condition = COND_GRUB_EMU_PCI;
};
module = {
name = emupci;
common = bus/emu/pci.c;
common = commands/lspci.c;
condition = COND_GRUB_EMU_PCI;
};
module = {
@ -631,6 +660,20 @@ module = {
emu = lib/emu/halt.c;
};
module = {
name = reboot;
i386 = lib/i386/reboot.c;
i386 = lib/i386/reboot_trampoline.S;
ia64_efi = lib/efi/reboot.c;
x86_64_efi = lib/efi/reboot.c;
powerpc_ieee1275 = lib/ieee1275/reboot.c;
sparc64_ieee1275 = lib/ieee1275/reboot.c;
mips_arc = lib/mips/arc/reboot.c;
mips_loongson = lib/mips/loongson/reboot.c;
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
common = commands/reboot.c;
};
module = {
name = hashsum;
common = commands/hashsum.c;
@ -731,11 +774,6 @@ module = {
common = commands/read.c;
};
module = {
name = reboot;
common = commands/reboot.c;
};
module = {
name = search;
common = commands/search_wrap.c;
@ -760,7 +798,7 @@ module = {
module = {
name = setpci;
common = commands/setpci.c;
enable = x86;
enable = pci;
};
module = {
@ -794,8 +832,6 @@ module = {
name = usbtest;
common = commands/usbtest.c;
enable = usb;
enable = emu;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
@ -844,6 +880,11 @@ module = {
common = disk/lvm.c;
};
module = {
name = ldm;
common = disk/ldm.c;
};
module = {
name = mdraid09;
common = disk/mdraid_linux.c;
@ -855,8 +896,8 @@ module = {
};
module = {
name = raid;
common = disk/raid.c;
name = diskfilter;
common = disk/diskfilter.c;
};
module = {
@ -909,8 +950,6 @@ module = {
name = usbms;
common = disk/usbms.c;
enable = usb;
enable = emu;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
@ -969,24 +1008,16 @@ module = {
};
module = {
name = afs_be;
common = fs/afs_be.c;
};
module = {
name = befs;
common = fs/befs.c;
};
module = {
name = befs_be;
common = fs/befs_be.c;
name = bfs;
common = fs/bfs.c;
};
module = {
name = btrfs;
common = fs/btrfs.c;
common = lib/crc.c;
cflags = '$(CFLAGS_POSIX) -Wno-undef';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
};
module = {
@ -994,6 +1025,21 @@ module = {
common = fs/cpio.c;
};
module = {
name = cpio_be;
common = fs/cpio_be.c;
};
module = {
name = newc;
common = fs/newc.c;
};
module = {
name = odc;
common = fs/odc.c;
};
module = {
name = ext2;
common = fs/ext2.c;
@ -1004,6 +1050,11 @@ module = {
common = fs/fat.c;
};
module = {
name = exfat;
common = fs/exfat.c;
};
module = {
name = fshelp;
common = fs/fshelp.c;
@ -1077,6 +1128,8 @@ module = {
module = {
name = squash4;
common = fs/squash4.c;
cflags = '$(CFLAGS_POSIX) -Wno-undef';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
};
module = {
@ -1112,6 +1165,11 @@ module = {
common = fs/zfs/zfs_fletcher.c;
};
module = {
name = zfscrypt;
common = fs/zfs/zfscrypt.c;
};
module = {
name = zfsinfo;
common = fs/zfs/zfsinfo.c;
@ -1247,6 +1305,13 @@ module = {
enable = x86;
};
module = {
name = plan9;
i386_pc = loader/i386/pc/plan9.c;
enable = i386_pc;
};
module = {
name = linux16;
i386_pc = loader/i386/pc/linux.c;
@ -1381,7 +1446,7 @@ module = {
extra_dist = script/yylex.l;
extra_dist = script/parser.y;
cflags = '$(CFLAGS_POSIX) -Wno-error';
cflags = '$(CFLAGS_POSIX)';
cppflags = '$(CPPFLAGS_POSIX)';
};
@ -1415,6 +1480,11 @@ module = {
common = partmap/sun.c;
};
module = {
name = part_plan;
common = partmap/plan.c;
};
module = {
name = part_dvh;
common = partmap/dvh.c;
@ -1452,9 +1522,7 @@ module = {
common = term/serial.c;
x86 = term/ns8250.c;
enable = emu;
enable = x86;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
@ -1602,9 +1670,13 @@ module = {
module = {
name = net;
common = net/net.c;
common = net/dns.c;
common = net/bootp.c;
common = net/ip.c;
common = net/udp.c;
common = net/tcp.c;
common = net/icmp.c;
common = net/icmp6.c;
common = net/ethernet.c;
common = net/arp.c;
common = net/netbuff.c;
@ -1615,6 +1687,11 @@ module = {
common = net/tftp.c;
};
module = {
name = http;
common = net/http.c;
};
module = {
name = ofnet;
common = net/drivers/ieee1275/ofnet.c;
@ -1656,6 +1733,14 @@ module = {
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
};
module = {
name = lzopio;
common = io/lzopio.c;
common = lib/minilzo/minilzo.c;
cflags = '$(CFLAGS_POSIX) -Wno-undef';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
};
module = {
name = testload;
common = commands/testload.c;
@ -1673,6 +1758,11 @@ module = {
enable = videomodules;
};
module = {
name = priority_queue;
common = lib/priority_queue.c;
};
module = {
name = time;
common = commands/time.c;
@ -1683,3 +1773,13 @@ module = {
common = commands/cacheinfo.c;
condition = COND_ENABLE_CACHE_STATS;
};
module = {
name = adler32;
common = lib/adler32.c;
};
module = {
name = crc64;
common = lib/crc64.c;
};

View file

@ -18,7 +18,6 @@
*/
#include <grub/symbol.h>
#include <grub/boot.h>
#include <grub/machine/boot.h>
/*

View file

@ -18,7 +18,6 @@
*/
#include <grub/symbol.h>
#include <grub/boot.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <multiboot.h>

View file

@ -19,7 +19,6 @@
#include <config.h>
#include <grub/symbol.h>
#include <grub/boot.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <multiboot.h>
@ -178,20 +177,21 @@ real_code_2:
pushw %es
popw %ds
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200
movl $0x200, %ecx
addl %ecx, %esi
#else
movl $(GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4), %ecx
movl $0x1000, %ecx
addl $0x200, %esi
#endif
movl $DATA_ADDR, %edi
call LOCAL(move_memory)
/* Check for multiboot signature. */
cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART)
movl $DATA_ADDR, %edi
3:
movl %ss:(%edi), %eax
cmpl $MULTIBOOT_HEADER_MAGIC, %eax
jz 1f
addl $4, %edi
cmpl $(DATA_ADDR + 0x1000), %edi
jne 3b
movl (ramdisk_image - start), %esi
movl (ramdisk_size - start), %ecx
@ -200,21 +200,13 @@ real_code_2:
1:
movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx
#else
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
#endif
movl $(DATA_ADDR + 0x1000), %edi
movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
addl $GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE, %ecx
2:
call LOCAL(move_memory)
movsbl %dh, %eax
movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART)
movsbl (reg_edx + 2 - start), %eax
movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)
movb $0xFF, %dh
ljmp $(DATA_ADDR >> 4), $0

View file

@ -0,0 +1,354 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/symbol.h>
#include <grub/offsets.h>
#include <grub/machine/boot.h>
#include <grub/machine/memory.h>
#include <grub/machine/kernel.h>
#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
.file "startup_raw.S"
.text
/* Tell GAS to generate 16-bit instructions so that this code works
in real mode. */
.code16
.globl start, _start
start:
_start:
LOCAL (base):
/*
* Guarantee that "main" is loaded at 0x0:0x8200.
*/
#ifdef __APPLE__
ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
#else
ljmp $0, $ABS(LOCAL (codestart))
#endif
/*
* This is a special data area.
*/
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
LOCAL(compressed_size):
.long 0
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
LOCAL(uncompressed_size):
.long 0
. = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
reed_solomon_redundancy:
.long 0
. = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
.short (LOCAL(reed_solomon_part) - _start)
/*
* This is the area for all of the special variables.
*/
. = _start + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE
LOCAL(boot_dev):
.byte 0xFF, 0xFF, 0xFF
LOCAL(boot_drive):
.byte 0x00
/* the real mode code continues... */
LOCAL (codestart):
cli /* we're not safe here! */
/* set up %ds, %ss, and %es */
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
/* set up the real mode/BIOS stack */
movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
movl %ebp, %esp
sti /* we're safe again */
/* save the boot drive */
ADDR32 movb %dl, LOCAL(boot_drive)
/* reset disk system (%ah = 0) */
int $0x13
/* transition to protected mode */
DATA32 call real_to_prot
/* The ".code32" directive takes GAS out of 16-bit mode. */
.code32
incl %eax
cld
call grub_gate_a20
movl LOCAL(compressed_size), %edx
addl $(LOCAL(decompressor_end) - LOCAL(reed_solomon_part)), %edx
movl reed_solomon_redundancy, %ecx
leal LOCAL(reed_solomon_part), %eax
cld
call EXT_C (grub_reed_solomon_recover)
jmp post_reed_solomon
#include "../../../kern/i386/realmode.S"
#include <rs_decoder.S>
.text
/*
* grub_gate_a20(int on)
*
* Gate address-line 20 for high memory.
*
* This routine is probably overconservative in what it does, but so what?
*
* It also eats any keystrokes in the keyboard buffer. :-(
*/
grub_gate_a20:
movl %eax, %edx
gate_a20_test_current_state:
/* first of all, test if already in a good state */
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_bios
ret
gate_a20_try_bios:
/* second, try a BIOS call */
pushl %ebp
call prot_to_real
.code16
movw $0x2400, %ax
testb %dl, %dl
jz 1f
incw %ax
1: int $0x15
DATA32 call real_to_prot
.code32
popl %ebp
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_system_control_port_a
ret
gate_a20_try_system_control_port_a:
/*
* In macbook, the keyboard test would hang the machine, so we move
* this forward.
*/
/* fourth, try the system control port A */
inb $0x92
andb $(~0x03), %al
testb %dl, %dl
jz 6f
orb $0x02, %al
6: outb $0x92
/* When turning off Gate A20, do not check the state strictly,
because a failure is not fatal usually, and Gate A20 is always
on some modern machines. */
testb %dl, %dl
jz 7f
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_keyboard_controller
7: ret
gate_a20_flush_keyboard_buffer:
inb $0x64
andb $0x02, %al
jnz gate_a20_flush_keyboard_buffer
2:
inb $0x64
andb $0x01, %al
jz 3f
inb $0x60
jmp 2b
3:
ret
gate_a20_try_keyboard_controller:
/* third, try the keyboard controller */
call gate_a20_flush_keyboard_buffer
movb $0xd1, %al
outb $0x64
4:
inb $0x64
andb $0x02, %al
jnz 4b
movb $0xdd, %al
testb %dl, %dl
jz 5f
orb $0x02, %al
5: outb $0x60
call gate_a20_flush_keyboard_buffer
/* output a dummy command (USB keyboard hack) */
movb $0xff, %al
outb $0x64
call gate_a20_flush_keyboard_buffer
call gate_a20_check_state
cmpb %al, %dl
/* everything failed, so restart from the beginning */
jnz gate_a20_try_bios
ret
gate_a20_check_state:
/* iterate the checking for a while */
movl $100, %ecx
1:
call 3f
cmpb %al, %dl
jz 2f
loop 1b
2:
ret
3:
pushl %ebx
pushl %ecx
xorl %eax, %eax
/* compare the byte at 0x8000 with that at 0x108000 */
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
pushl %ebx
/* save the original byte in CL */
movb (%ebx), %cl
/* store the value at 0x108000 in AL */
addl $0x100000, %ebx
movb (%ebx), %al
/* try to set one less value at 0x8000 */
popl %ebx
movb %al, %ch
decb %ch
movb %ch, (%ebx)
/* serialize */
outb %al, $0x80
outb %al, $0x80
/* obtain the value at 0x108000 in CH */
pushl %ebx
addl $0x100000, %ebx
movb (%ebx), %ch
/* this result is 1 if A20 is on or 0 if it is off */
subb %ch, %al
xorb $1, %al
/* restore the original */
popl %ebx
movb %cl, (%ebx)
popl %ecx
popl %ebx
ret
LOCAL(reed_solomon_part):
/*
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
* This uses the a.out kludge to load raw binary to the area starting at 1MB,
* and relocates itself after loaded.
*/
.p2align 2 /* force 4-byte alignment */
multiboot_header:
/* magic */
.long 0x1BADB002
/* flags */
.long (1 << 16)
/* checksum */
.long -0x1BADB002 - (1 << 16)
/* header addr */
.long multiboot_header - _start + 0x100000 + 0x200
/* load addr */
.long 0x100000
/* load end addr */
.long 0
/* bss end addr */
.long 0
/* entry addr */
.long multiboot_entry - _start + 0x100000 + 0x200
multiboot_entry:
.code32
/* obtain the boot device */
movl 12(%ebx), %edx
movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp
movl %ebp, %esp
/* relocate the code */
movl $(LOCAL(decompressor_end) + 0x200), %ecx
addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx
movl $0x100000, %esi
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
cld
rep
movsb
/* jump to the real address */
movl $multiboot_trampoline, %eax
jmp *%eax
multiboot_trampoline:
/* fill the boot information */
movl %edx, LOCAL(boot_dev)
shrl $24, %edx
/* enter the usual booting */
call prot_to_real
.code16
jmp LOCAL (codestart)
.code32
post_reed_solomon:
#ifdef ENABLE_LZMA
movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
movl $LOCAL(decompressor_end), %esi
pushl %edi
movl LOCAL (uncompressed_size), %ecx
leal (%edi, %ecx), %ebx
/* Don't remove this push: it's an argument. */
push %ecx
call _LzmaDecodeA
pop %ecx
/* _LzmaDecodeA clears DF, so no need to run cld */
popl %esi
#endif
movl LOCAL(boot_dev), %edx
movl $prot_to_real, %edi
movl $real_to_prot, %ecx
jmp *%esi
#ifdef ENABLE_LZMA
#include "lzma_decode.S"
#endif
.p2align 4
LOCAL(decompressor_end):

View file

@ -38,13 +38,13 @@ start:
bal codestart
nop
base:
. = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
compressed_size:
.long 0
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
uncompressed_size:
.long 0
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
uncompressed_addr:
.long 0
codestart:
@ -240,9 +240,9 @@ cmdlinedone:
subu $a0, $a0, $t0
addu $a0, $a0, $s0
lw $a1, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a1, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
lw $a2, (GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a3, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
move $s1, $a1
/* $a0 contains source compressed address, $a1 is destination,

View file

@ -17,7 +17,6 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/boot.h>
#include <grub/machine/boot.h>
.text
@ -29,9 +28,6 @@ pic_base:
call boot_continue
mov %o4, CIF_REG
. = _start + GRUB_BOOT_MACHINE_VER_MAJ
boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
/* The offsets to these locations are defined by the
* GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h,
* and grub-setup uses this to patch these next three values as needed.
@ -44,6 +40,7 @@ boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
* After loading in that block we will execute it by jumping to the
* load address plus the size of the prepended A.OUT header (32 bytes).
*/
. = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH
boot_path:
. = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE
boot_path_end:

View file

@ -17,7 +17,6 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/boot.h>
#include <grub/machine/boot.h>
#include <grub/offsets.h>

View file

@ -97,8 +97,6 @@ grub_cs5536_smbus_wait (grub_port_t smbbase)
if (grub_get_time_ms () > start + 40)
return grub_error (GRUB_ERR_IO, "SM stalled");
}
return GRUB_ERR_NONE;
}
grub_err_t

View file

@ -1152,8 +1152,8 @@ grub_ohci_check_transfer (grub_usb_controller_t dev,
return parse_halt (dev, transfer, actual);
/* Finished ED detection */
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) ==
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xfU) ==
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xfU) ) /* Empty ED */
{
/* Check the HALT bit */
/* It looks like nonsense - it was tested previously...
@ -1426,7 +1426,7 @@ static struct grub_usb_controller_dev usb_controller =
.detect_dev = grub_ohci_detect_dev
};
static void *fini_hnd;
static struct grub_preboot *fini_hnd;
GRUB_MOD_INIT(ohci)
{

View file

@ -36,11 +36,33 @@ GRUB_MOD_LICENSE ("GPLv3+");
typedef enum
{
GRUB_UHCI_REG_USBCMD = 0x00,
GRUB_UHCI_REG_USBINTR = 0x04,
GRUB_UHCI_REG_FLBASEADD = 0x08,
GRUB_UHCI_REG_PORTSC1 = 0x10,
GRUB_UHCI_REG_PORTSC2 = 0x12
GRUB_UHCI_REG_PORTSC2 = 0x12,
GRUB_UHCI_REG_USBLEGSUP = 0xc0
} grub_uhci_reg_t;
/* R/WC legacy support bits */
#define GRUB_UHCI_LEGSUP_END_A20GATE (1 << 15)
#define GRUB_UHCI_TRAP_BY_64H_WSTAT (1 << 11)
#define GRUB_UHCI_TRAP_BY_64H_RSTAT (1 << 10)
#define GRUB_UHCI_TRAP_BY_60H_WSTAT (1 << 9)
#define GRUB_UHCI_TRAP_BY_60H_RSTAT (1 << 8)
/* Reset all legacy support - clear all R/WC bits and all R/W bits */
#define GRUB_UHCI_RESET_LEGSUP_SMI ( GRUB_UHCI_LEGSUP_END_A20GATE \
| GRUB_UHCI_TRAP_BY_64H_WSTAT \
| GRUB_UHCI_TRAP_BY_64H_RSTAT \
| GRUB_UHCI_TRAP_BY_60H_WSTAT \
| GRUB_UHCI_TRAP_BY_60H_RSTAT )
/* Some UHCI commands */
#define GRUB_UHCI_CMD_RUN_STOP (1 << 0)
#define GRUB_UHCI_CMD_HCRESET (1 << 1)
#define GRUB_UHCI_CMD_MAXP (1 << 7)
/* Important bits in structures */
#define GRUB_UHCI_LINK_TERMINATE 1
#define GRUB_UHCI_LINK_QUEUE_HEAD 2
@ -181,6 +203,11 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
if (class != 0x0c || subclass != 0x03 || interf != 0x00)
return 0;
/* Set bus master - needed for coreboot or broken BIOSes */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
grub_pci_write_word(addr,
GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr));
/* Determine IO base address. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4);
base = grub_pci_read (addr);
@ -195,6 +222,19 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
u->iobase = base & GRUB_UHCI_IOMASK;
/* Reset PIRQ and SMI */
addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP);
grub_pci_write_word(addr, GRUB_UHCI_RESET_LEGSUP_SMI);
/* Reset the HC */
grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, GRUB_UHCI_CMD_HCRESET);
grub_millisleep(5);
/* Disable interrupts and commands (just to be safe) */
grub_uhci_writereg16(u, GRUB_UHCI_REG_USBINTR, 0);
/* Finish HC reset, HC remains disabled */
grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, 0);
/* Read back to be sure PCI write is done */
grub_uhci_readreg16(u, GRUB_UHCI_REG_USBCMD);
/* Reserve a page for the frame list. */
u->framelist = grub_memalign (4096, 4096);
if (! u->framelist)
@ -252,9 +292,6 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
u->td[N_TD - 2].linkptr = 0;
u->tdfree = u->td;
/* Make sure UHCI is disabled! */
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 0);
/* Setup the frame list pointers. Since no isochronous transfers
are and will be supported, they all point to the (same!) queue
head. */
@ -285,7 +322,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
u->qh[N_QH - 1].linkptr = 1;
/* Enable UHCI again. */
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7));
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD,
GRUB_UHCI_CMD_RUN_STOP | GRUB_UHCI_CMD_MAXP);
/* UHCI is initialized and ready for transfers. */
grub_dprintf ("uhci", "UHCI initialized\n");
@ -506,8 +544,11 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev,
{
grub_size_t actual = 0;
/* Terminate and free. */
td_prev->linkptr2 = 0;
td_prev->linkptr = 1;
if (td_prev)
{
td_prev->linkptr2 = 0;
td_prev->linkptr = 1;
}
if (cdata->td_first)
grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual);

View file

@ -340,7 +340,7 @@ grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc)
void
grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc)
{
grub_list_remove (GRUB_AS_LIST_P (&attach_hooks), GRUB_AS_LIST (desc));
grub_list_remove (GRUB_AS_LIST (desc));
}

View file

@ -167,11 +167,13 @@ grub_usb_add_hub (grub_usb_device_t dev)
if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
== GRUB_USB_EP_INTERRUPT)
{
grub_size_t len;
dev->hub_endpoint = endp;
len = endp->maxpacket;
if (len > sizeof (dev->statuschange))
len = sizeof (dev->statuschange);
dev->hub_transfer
= grub_usb_bulk_read_background (dev, endp->endp_addr,
grub_min (endp->maxpacket,
sizeof (dev->statuschange)),
= grub_usb_bulk_read_background (dev, endp->endp_addr, len,
(char *) &dev->statuschange);
break;
}
@ -323,7 +325,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
grub_usb_err_t err;
unsigned i;
grub_uint8_t changed;
grub_size_t actual;
grub_size_t actual, len;
int j, total;
if (!dev->hub_transfer)
@ -336,10 +338,11 @@ poll_nonroot_hub (grub_usb_device_t dev)
changed = dev->statuschange;
len = dev->hub_endpoint->maxpacket;
if (len > sizeof (dev->statuschange))
len = sizeof (dev->statuschange);
dev->hub_transfer
= grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr,
grub_min (dev->hub_endpoint->maxpacket,
sizeof (dev->statuschange)),
= grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, len,
(char *) &dev->statuschange);
if (err || actual == 0 || changed == 0)

View file

@ -138,6 +138,7 @@ iszero (grub_uint8_t *reg, int size)
return 1;
}
#if defined (__i386__) || defined (__x86_64__)
grub_err_t
grub_acpi_create_ebda (void)
{
@ -165,7 +166,7 @@ grub_acpi_create_ebda (void)
return 0;
}
ebda = (grub_uint8_t *) UINT_TO_PTR ((*((grub_uint16_t *)0x40e)) << 4);
ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4);
ebda_kb_len = *(grub_uint16_t *) ebda;
if (! ebda || ebda_kb_len > 16)
ebda_kb_len = 0;
@ -173,14 +174,14 @@ grub_acpi_create_ebda (void)
/* FIXME: use low-memory mm allocation once it's available. */
grub_mmap_iterate (find_hook);
targetebda = (grub_uint8_t *) UINT_TO_PTR (highestlow);
targetebda = (grub_uint8_t *) (grub_addr_t) highestlow;
grub_dprintf ("acpi", "creating ebda @%llx\n",
(unsigned long long) highestlow);
if (! highestlow)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't find space for the new EBDA");
mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len,
mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ebda_len,
GRUB_MEMORY_RESERVED);
if (! mmapregion)
return grub_errno;
@ -297,6 +298,7 @@ grub_acpi_create_ebda (void)
return GRUB_ERR_NONE;
}
#endif
/* Create tables common to ACPIv1 and ACPIv2+ */
static void
@ -328,13 +330,13 @@ setup_common_tables (void)
if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE,
sizeof (fadt->hdr.signature)) == 0)
{
fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt);
fadt->dsdt_addr = (grub_addr_t) table_dsdt;
fadt->facs_addr = facs_addr;
/* Does a revision 2 exist at all? */
if (fadt->hdr.revision >= 3)
{
fadt->dsdt_xaddr = PTR_TO_UINT64 (table_dsdt);
fadt->dsdt_xaddr = (grub_addr_t) table_dsdt;
fadt->facs_xaddr = facs_addr;
}
@ -365,7 +367,7 @@ setup_common_tables (void)
rsdt->creator_rev = root_creator_rev;
for (cur = acpi_tables; cur; cur = cur->next)
*(rsdt_entry++) = PTR_TO_UINT32 (cur->addr);
*(rsdt_entry++) = (grub_addr_t) cur->addr;
/* Recompute checksum. */
rsdt->checksum = 0;
@ -383,7 +385,7 @@ setv1table (void)
sizeof (rsdpv1_new->signature));
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
rsdpv1_new->revision = 0;
rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
rsdpv1_new->rsdt_addr = (grub_addr_t) rsdt_addr;
rsdpv1_new->checksum = 0;
rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new,
sizeof (*rsdpv1_new));
@ -408,7 +410,7 @@ setv2table (void)
xsdt_entry = (grub_uint64_t *)(xsdt + 1);
for (cur = acpi_tables; cur; cur = cur->next)
*(xsdt_entry++) = PTR_TO_UINT64 (cur->addr);
*(xsdt_entry++) = (grub_addr_t) cur->addr;
grub_memcpy (&(xsdt->signature), "XSDT", 4);
xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables;
xsdt->revision = 1;
@ -428,12 +430,12 @@ setv2table (void)
grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid,
sizeof (rsdpv2_new->rsdpv1.oemid));
rsdpv2_new->rsdpv1.revision = rev2;
rsdpv2_new->rsdpv1.rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
rsdpv2_new->rsdpv1.rsdt_addr = (grub_addr_t) rsdt_addr;
rsdpv2_new->rsdpv1.checksum = 0;
rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum
(&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1));
rsdpv2_new->length = sizeof (*rsdpv2_new);
rsdpv2_new->xsdt_addr = PTR_TO_UINT64 (xsdt);
rsdpv2_new->xsdt_addr = (grub_addr_t) xsdt;
rsdpv2_new->checksum = 0;
rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new,
rsdpv2_new->length);
@ -463,7 +465,6 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
struct grub_arg_list *state = ctxt->state;
struct grub_acpi_rsdp_v10 *rsdp;
struct efiemu_acpi_table *cur, *t;
grub_err_t err;
int i, mmapregion;
int numoftables;
@ -506,7 +507,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
/* Set revision variables to replicate the same version as host. */
rev1 = ! rsdp->revision;
rev2 = rsdp->revision;
rsdt = (struct grub_acpi_table_header *) UINT_TO_PTR (rsdp->rsdt_addr);
rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr;
/* Load host tables. */
for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
@ -516,7 +517,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
char signature[5];
struct efiemu_acpi_table *table;
struct grub_acpi_table_header *curtable
= (struct grub_acpi_table_header *) UINT_TO_PTR (*entry_ptr);
= (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr;
signature[4] = 0;
for (i = 0; i < 4;i++)
signature[i] = grub_tolower (curtable->signature[i]);
@ -540,7 +541,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
/* Load DSDT if not excluded. */
dsdt = (struct grub_acpi_table_header *)
UINT_TO_PTR (fadt->dsdt_addr);
(grub_addr_t) fadt->dsdt_addr;
if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt"))
&& (! load_only || grub_strword (load_only, "dsdt"))
&& dsdt->length >= sizeof (*dsdt))
@ -648,15 +649,17 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
{
grub_file_close (file);
free_tables ();
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't read file %s", args[i]);
return grub_errno;
}
if (grub_file_read (file, buf, size) != (int) size)
{
grub_file_close (file);
free_tables ();
return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[i]);
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
args[i]);
return grub_errno;
}
grub_file_close (file);
@ -732,13 +735,20 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
}
acpi_tables = 0;
if (! state[9].set && (err = grub_acpi_create_ebda ()))
#if defined (__i386__) || defined (__x86_64__)
if (! state[9].set)
{
rsdpv1_new = 0;
rsdpv2_new = 0;
grub_mmap_free_and_unregister (mmapregion);
return err;
grub_err_t err;
err = grub_acpi_create_ebda ();
if (err)
{
rsdpv1_new = 0;
rsdpv2_new = 0;
grub_mmap_free_and_unregister (mmapregion);
return err;
}
}
#endif
#ifdef GRUB_MACHINE_EFI
{

View file

@ -33,6 +33,7 @@ typedef uint8_t grub_uint8_t;
#endif
#include <grub/acpi.h>
#include <grub/i18n.h>
#ifndef GRUB_DSDT_TEST
#include <grub/misc.h>
@ -327,6 +328,6 @@ grub_acpi_halt (void)
grub_millisleep (1500);
grub_printf ("ACPI shutdown failed\n");
grub_puts_ (N_("ACPI shutdown failed"));
}
#endif

View file

@ -31,17 +31,17 @@ static grub_err_t (*grub_loader_boot_func) (void);
static grub_err_t (*grub_loader_unload_func) (void);
static int grub_loader_noreturn;
struct grub_preboot_t
struct grub_preboot
{
grub_err_t (*preboot_func) (int);
grub_err_t (*preboot_rest_func) (void);
grub_loader_preboot_hook_prio_t prio;
struct grub_preboot_t *next;
struct grub_preboot_t *prev;
struct grub_preboot *next;
struct grub_preboot *prev;
};
static int grub_loader_loaded;
static struct grub_preboot_t *preboots_head = 0,
static struct grub_preboot *preboots_head = 0,
*preboots_tail = 0;
int
@ -51,18 +51,18 @@ grub_loader_is_loaded (void)
}
/* Register a preboot hook. */
void *
struct grub_preboot *
grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
grub_err_t (*preboot_rest_func) (void),
grub_loader_preboot_hook_prio_t prio)
{
struct grub_preboot_t *cur, *new_preboot;
struct grub_preboot *cur, *new_preboot;
if (! preboot_func && ! preboot_rest_func)
return 0;
new_preboot = (struct grub_preboot_t *)
grub_malloc (sizeof (struct grub_preboot_t));
new_preboot = (struct grub_preboot *)
grub_malloc (sizeof (struct grub_preboot));
if (! new_preboot)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added");
@ -96,9 +96,9 @@ grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
}
void
grub_loader_unregister_preboot_hook (void *hnd)
grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
{
struct grub_preboot_t *preb = hnd;
struct grub_preboot *preb = hnd;
if (preb->next)
preb->next->prev = preb->prev;
@ -143,7 +143,7 @@ grub_err_t
grub_loader_boot (void)
{
grub_err_t err = GRUB_ERR_NONE;
struct grub_preboot_t *cur;
struct grub_preboot *cur;
if (! grub_loader_loaded)
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");

View file

@ -31,14 +31,14 @@ grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)),
unsigned long hits, misses;
grub_disk_cache_get_performance (&hits, &misses);
grub_printf ("Disk cache: hits = %lu, misses = %lu ", hits, misses);
grub_printf_ (N_("Disk cache: hits = %lu, misses = %lu "), hits, misses);
if (hits + misses)
{
unsigned long ratio = hits * 10000 / (hits + misses);
grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100);
}
else
grub_printf ("(N/A)\n");
grub_puts_ (N_("(N/A)"));
return 0;
}

View file

@ -42,8 +42,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
if (argc != 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
grub_printf ("Compare file `%s' with `%s':\n", args[0],
args[1]);
grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0],
args[1]);
file1 = grub_file_open (args[0]);
file2 = grub_file_open (args[1]);
@ -51,9 +51,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
goto cleanup;
if (grub_file_size (file1) != grub_file_size (file2))
grub_printf ("Files differ in size: %llu [%s], %llu [%s]\n",
(unsigned long long) grub_file_size (file1), args[0],
(unsigned long long) grub_file_size (file2), args[1]);
grub_printf_ (N_("Files differ in size: %llu [%s], %llu [%s]\n"),
(unsigned long long) grub_file_size (file1), args[0],
(unsigned long long) grub_file_size (file2), args[1]);
else
{
pos = 0;
@ -78,9 +78,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
{
if (buf1[i] != buf2[i])
{
grub_printf ("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n",
(unsigned long long) (i + pos), buf1[i], args[0],
buf2[i], args[1]);
grub_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"),
(unsigned long long) (i + pos), buf1[i],
args[0], buf2[i], args[1]);
goto cleanup;
}
}
@ -89,7 +89,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
}
while (rd2);
grub_printf ("The files are identical.\n");
/* TRANSLATORS: it's always exactly 2 files. */
grub_printf_ (N_("The files are identical.\n"));
}
cleanup:

View file

@ -56,24 +56,24 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
{
grub_target_addr_t base;
grub_printf ("Found graphic card: %s\n", p->name);
grub_dprintf ("fixvideo", "Found graphic card: %s\n", p->name);
addr += 8 + p->mmio_bar * 4;
base = grub_pci_read (addr);
if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
(base & GRUB_PCI_ADDR_MEM_PREFETCH))
grub_printf ("Invalid MMIO bar %d\n", p->mmio_bar);
grub_dprintf ("fixvideo", "Invalid MMIO bar %d\n", p->mmio_bar);
else
{
base &= GRUB_PCI_ADDR_MEM_MASK;
base += p->mmio_reg;
if (*((volatile grub_uint32_t *) base) != p->mmio_old)
grub_printf ("Old value don't match\n");
grub_dprintf ("fixvideo", "Old value doesn't match\n");
else
{
*((volatile grub_uint32_t *) base) = 0;
if (*((volatile grub_uint32_t *) base))
grub_printf ("Set MMIO fails\n");
grub_dprintf ("fixvideo", "Setting MMIO fails\n");
}
}
@ -82,7 +82,7 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
p++;
}
grub_printf ("Unknown graphic card: %x\n", pciid);
grub_dprintf ("fixvideo", "Unknown graphic card: %x\n", pciid);
}
return 0;

View file

@ -49,7 +49,7 @@ enable_rom_area (void)
rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
if (*rom_ptr != BLANK_MEM)
{
grub_printf ("ROM image is present.\n");
grub_puts_ (N_("ROM image is present."));
return 0;
}
@ -67,7 +67,7 @@ enable_rom_area (void)
*rom_ptr = 0;
if (*rom_ptr != 0)
{
grub_printf ("Can\'t enable ROM area.\n");
grub_puts_ (N_("Can\'t enable ROM area."));
return 0;
}
@ -209,7 +209,7 @@ GRUB_MOD_INIT(loadbios)
0, N_("Fake BIOS."));
cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
"BIOS_DUMP [INT10_DUMP]",
N_("BIOS_DUMP [INT10_DUMP]"),
N_("Load BIOS dump."));
}

View file

@ -231,7 +231,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
grub_printf ("New MBR is written to '%s'\n", args[0]);
grub_printf_ (N_("New MBR is written to '%s'\n"), args[0]);
return GRUB_ERR_NONE;
}

View file

@ -24,13 +24,12 @@
GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t
static grub_err_t __attribute__ ((noreturn))
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
grub_halt ();
return 0;
}
static grub_command_t cmd;

View file

@ -141,7 +141,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
grub_file_close (file);
if (err)
{
grub_printf ("%s: READ ERROR\n", p);
grub_printf_ (N_("%s: READ ERROR\n"), p);
if (!keep)
{
grub_file_close (hashlist);
@ -155,7 +155,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
}
if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0)
{
grub_printf ("%s: HASH MISMATCH\n", p);
grub_printf_ (N_("%s: HASH MISMATCH\n"), p);
if (!keep)
{
grub_file_close (hashlist);
@ -166,7 +166,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
mismatch++;
continue;
}
grub_printf ("%s: OK\n", p);
grub_printf_ (N_("%s: OK\n"), p);
}
if (mismatch || unread)
return grub_error (GRUB_ERR_TEST_FAILURE,
@ -257,8 +257,8 @@ static grub_extcmd_t cmd, cmd_md5, cmd_sha1, cmd_sha256, cmd_sha512, cmd_crc;
GRUB_MOD_INIT(hashsum)
{
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0,
"hashsum -h HASH [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]",
N_("-h HASH [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]"),
N_("Compute or check hash checksum."),
options);
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0,

View file

@ -165,22 +165,20 @@ grub_hdparm_set_val_cmd (const char * msg, int val,
}
static const char *
le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes)
le16_to_char (grub_uint16_t *dest, const grub_uint16_t * src16, unsigned bytes)
{
grub_uint16_t * dest16 = (grub_uint16_t *) dest;
unsigned i;
for (i = 0; i < bytes / 2; i++)
dest16[i] = grub_be_to_cpu16 (src16[i]);
return dest;
dest[i] = grub_be_to_cpu16 (src16[i]);
dest[i] = 0;
return (char *) dest;
}
static void
grub_hdparm_print_identify (const char * idbuf)
grub_hdparm_print_identify (const grub_uint16_t * idw)
{
const grub_uint16_t * idw = (const grub_uint16_t *) idbuf;
/* Print identity strings. */
char tmp[40];
grub_uint16_t tmp[21];
grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8));
grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
@ -377,7 +375,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
/* Print/dump IDENTIFY. */
if (ident || dumpid)
{
char buf[GRUB_DISK_SECTOR_SIZE];
grub_uint16_t buf[GRUB_DISK_SECTOR_SIZE / 2];
if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE,
0, 0, buf, sizeof (buf)))
grub_printf ("Cannot read ATA IDENTIFY data\n");
@ -386,7 +384,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
if (ident)
grub_hdparm_print_identify (buf);
if (dumpid)
hexdump (0, buf, sizeof (buf));
hexdump (0, (char *) buf, sizeof (buf));
}
}

View file

@ -20,6 +20,7 @@
#include <grub/command.h>
#include <grub/misc.h>
#include <grub/cmos.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -86,11 +87,11 @@ static grub_command_t cmd, cmd_clean;
GRUB_MOD_INIT(cmostest)
{
cmd = grub_register_command ("cmostest", grub_cmd_cmostest,
"cmostest BYTE:BIT",
"Test bit at BYTE:BIT in CMOS.");
N_("BYTE:BIT"),
N_("Test bit at BYTE:BIT in CMOS."));
cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean,
"cmosclean BYTE:BIT",
"Clean bit at BYTE:BIT in CMOS.");
N_("BYTE:BIT"),
N_("Clean bit at BYTE:BIT in CMOS."));
}
GRUB_MOD_FINI(cmostest)

View file

@ -32,7 +32,7 @@
GRUB_MOD_LICENSE ("GPLv3+");
/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13);
static grub_uint32_t *const int13slot = (grub_uint32_t *) (4 * 0x13);
/* Remember to update enum opt_idxs accordingly. */
static const struct grub_arg_option options[] = {
@ -178,11 +178,11 @@ list_mappings (void)
/* Show: list mappings. */
if (! map_head)
{
grub_printf ("No drives have been remapped\n");
grub_puts_ (N_("No drives have been remapped"));
return GRUB_ERR_NONE;
}
grub_printf ("OS disk #num ------> GRUB/BIOS device\n");
grub_puts_ (N_("OS disk #num ------> GRUB/BIOS device"));
drivemap_node_t *curnode = map_head;
while (curnode)
{
@ -363,7 +363,7 @@ uninstall_int13_handler (void)
static int
grub_get_root_biosnumber_drivemap (void)
{
char *biosnum;
const char *biosnum;
int ret = -1;
grub_device_t dev;

View file

@ -74,27 +74,27 @@ grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)),
if (!grub_apm_get_info (&info))
return grub_error (GRUB_ERR_IO, "no APM found");
grub_printf ("Vesion %u.%u\n"
"32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n"
"16-bit CS = 0x%x, len = 0x%x\n"
"DS = 0x%x, len = 0x%x\n",
info.version >> 8, info.version & 0xff,
info.cseg, info.cseg_len, info.offset,
info.cseg_16, info.cseg_16_len,
info.dseg, info.dseg_len);
grub_printf_ (N_("Vesion %u.%u\n"
"32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n"
"16-bit CS = 0x%x, len = 0x%x\n"
"DS = 0x%x, len = 0x%x\n"),
info.version >> 8, info.version & 0xff,
info.cseg, info.cseg_len, info.offset,
info.cseg_16, info.cseg_16_len,
info.dseg, info.dseg_len);
grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED
? "16-bit protected interface supported\n"
: "16-bit protected interface unsupported\n");
? _("16-bit protected interface supported\n")
: _("16-bit protected interface unsupported\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED
? "32-bit protected interface supported\n"
: "32-bit protected interface unsupported\n");
? _("32-bit protected interface supported\n")
: _("32-bit protected interface unsupported\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN
? "CPU Idle slows down processor\n"
: "CPU Idle doesn't slow down processor\n");
? _("CPU Idle slows down processor\n")
: _("CPU Idle doesn't slow down processor\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED
? "APM disabled\n" : "APM enabled\n");
? _("APM disabled\n") : _("APM enabled\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED
? "APM disengaged\n" : "APM engaged\n");
? _("APM disengaged\n") : _("APM engaged\n"));
return GRUB_ERR_NONE;
}

View file

@ -26,6 +26,7 @@
#include <grub/extcmd.h>
#include <grub/cpu/io.h>
#include <grub/loader.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv2+");
@ -35,23 +36,23 @@ static int keylen = 0;
static int noled = 0;
static const struct grub_arg_option options[] =
{
{"num", 'n', 0, "set numlock mode", "[on|off]", ARG_TYPE_STRING},
{"caps", 'c', 0, "set capslock mode", "[on|off]", ARG_TYPE_STRING},
{"scroll", 's', 0, "set scrolllock mode", "[on|off]", ARG_TYPE_STRING},
{"insert", 0, 0, "set insert mode", "[on|off]", ARG_TYPE_STRING},
{"pause", 0, 0, "set pause mode", "[on|off]", ARG_TYPE_STRING},
{"left-shift", 0, 0, "press left shift", "[on|off]", ARG_TYPE_STRING},
{"right-shift", 0, 0, "press right shift", "[on|off]", ARG_TYPE_STRING},
{"sysrq", 0, 0, "press SysRq", "[on|off]", ARG_TYPE_STRING},
{"numkey", 0, 0, "press NumLock key", "[on|off]", ARG_TYPE_STRING},
{"capskey", 0, 0, "press CapsLock key", "[on|off]", ARG_TYPE_STRING},
{"scrollkey", 0, 0, "press ScrollLock key", "[on|off]", ARG_TYPE_STRING},
{"insertkey", 0, 0, "press Insert key", "[on|off]", ARG_TYPE_STRING},
{"left-alt", 0, 0, "press left alt", "[on|off]", ARG_TYPE_STRING},
{"right-alt", 0, 0, "press right alt", "[on|off]", ARG_TYPE_STRING},
{"left-ctrl", 0, 0, "press left ctrl", "[on|off]", ARG_TYPE_STRING},
{"right-ctrl", 0, 0, "press right ctrl", "[on|off]", ARG_TYPE_STRING},
{"no-led", 0, 0, "don't update LED state", 0, 0},
{"num", 'n', 0, N_("set numlock mode"), "[on|off]", ARG_TYPE_STRING},
{"caps", 'c', 0, N_("set capslock mode"), "[on|off]", ARG_TYPE_STRING},
{"scroll", 's', 0, N_("set scrolllock mode"), "[on|off]", ARG_TYPE_STRING},
{"insert", 0, 0, N_("set insert mode"), "[on|off]", ARG_TYPE_STRING},
{"pause", 0, 0, N_("set pause mode"), "[on|off]", ARG_TYPE_STRING},
{"left-shift", 0, 0, N_("press left shift"), "[on|off]", ARG_TYPE_STRING},
{"right-shift", 0, 0, N_("press right shift"), "[on|off]", ARG_TYPE_STRING},
{"sysrq", 0, 0, N_("press SysRq"), "[on|off]", ARG_TYPE_STRING},
{"numkey", 0, 0, N_("press NumLock key"), "[on|off]", ARG_TYPE_STRING},
{"capskey", 0, 0, N_("press CapsLock key"), "[on|off]", ARG_TYPE_STRING},
{"scrollkey", 0, 0, N_("press ScrollLock key"), "[on|off]", ARG_TYPE_STRING},
{"insertkey", 0, 0, N_("press Insert key"), "[on|off]", ARG_TYPE_STRING},
{"left-alt", 0, 0, N_("press left alt"), "[on|off]", ARG_TYPE_STRING},
{"right-alt", 0, 0, N_("press right alt"), "[on|off]", ARG_TYPE_STRING},
{"left-ctrl", 0, 0, N_("press left ctrl"), "[on|off]", ARG_TYPE_STRING},
{"right-ctrl", 0, 0, N_("press right ctrl"), "[on|off]", ARG_TYPE_STRING},
{"no-led", 0, 0, N_("don't update LED state"), 0, 0},
{0, 0, 0, 0, 0, 0}
};
static int simple_flag_offsets[]
@ -62,8 +63,8 @@ static grub_uint32_t andmask = 0xffffffff, ormask = 0;
struct
keysym
{
char *unshifted_name; /* the name in unshifted state */
char *shifted_name; /* the name in shifted state */
const char *unshifted_name; /* the name in unshifted state */
const char *shifted_name; /* the name in shifted state */
unsigned char unshifted_ascii; /* the ascii code in unshifted state */
unsigned char shifted_ascii; /* the ascii code in shifted state */
unsigned char keycode; /* keyboard scancode */
@ -364,13 +365,13 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args)
}
static grub_extcmd_t cmd;
static void *preboot_hook;
static struct grub_preboot *preboot_hook;
GRUB_MOD_INIT (sendkey)
{
cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0,
"sendkey [KEYSTROKE1] [KEYSTROKE2] ...",
"Emulate a keystroke", options);
N_("[KEYSTROKE1] [KEYSTROKE2] ..."),
N_("Emulate a keystroke"), options);
preboot_hook
= grub_loader_register_preboot_hook (grub_sendkey_preboot,

View file

@ -31,7 +31,7 @@ grub_cmd_suspend (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
grub_printf ("Run 'go' to resume GRUB.\n");
grub_puts_ (N_("Run 'go' to resume GRUB."));
grub_ieee1275_enter ();
grub_cls ();
return 0;

View file

@ -344,7 +344,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
int bsd_part = -1;
{
grub_device_t dev;
char *hdbiasstr;
const char *hdbiasstr;
int hdbias = 0;
hdbiasstr = grub_env_get ("legacy_hdbias");
if (hdbiasstr)
@ -723,7 +723,7 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
grub_printf ("Enter password:");
grub_puts_ (N_("Enter password: "));
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
return GRUB_ACCESS_DENIED;

View file

@ -43,7 +43,7 @@ open_envblk_file (char *filename)
if (! filename)
{
char *prefix;
const char *prefix;
prefix = grub_env_get ("prefix");
if (prefix)
@ -346,7 +346,7 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
while (argc)
{
char *value;
const char *value;
value = grub_env_get (args[0]);
if (value)

View file

@ -26,13 +26,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
static const char *names[] =
{
[GRUB_MEMORY_AVAILABLE] = "available",
[GRUB_MEMORY_RESERVED] = "reserved",
[GRUB_MEMORY_ACPI] = "ACPI reclamaible",
[GRUB_MEMORY_NVS] = "NVS",
[GRUB_MEMORY_BADRAM] = "BadRAM",
[GRUB_MEMORY_CODE] = "firmware code",
[GRUB_MEMORY_HOLE] = "hole"
[GRUB_MEMORY_AVAILABLE] = N_("available"),
[GRUB_MEMORY_RESERVED] = N_("reserved"),
[GRUB_MEMORY_ACPI] = N_("ACPI reclamaible"),
[GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage"),
[GRUB_MEMORY_BADRAM] = N_("BadRAM"),
[GRUB_MEMORY_CODE] = N_("firmware code"),
[GRUB_MEMORY_HOLE] = N_("hole")
};
static grub_err_t
@ -46,11 +46,11 @@ grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)),
grub_memory_type_t type)
{
if (type < ARRAY_SIZE (names) && names[type])
grub_printf ("base_addr = 0x%llx, length = 0x%llx, %s\n",
(long long) addr, (long long) size, names[type]);
grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"),
(long long) addr, (long long) size, _(names[type]));
else
grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n",
(long long) addr, (long long) size, type);
grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"),
(long long) addr, (long long) size, type);
return 0;
}
#ifndef GRUB_MACHINE_EMU

View file

@ -29,7 +29,7 @@ struct grub_pci_classname
{
int class;
int subclass;
char *desc;
const char *desc;
};
static const struct grub_pci_classname grub_pci_classes[] =

View file

@ -31,7 +31,7 @@ static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword;
static const struct grub_arg_option options[] =
{
{0, 'v', 0, N_("Save read value into variable VARNAME."),
"VARNAME", ARG_TYPE_STRING},
N_("VARNAME"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};

View file

@ -28,19 +28,19 @@
static const struct grub_arg_option options[] =
{
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
N_("Menu entry type."), "STRING", ARG_TYPE_STRING},
N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
{"users", 2, 0,
N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING},
N_("Users allowed to boot this entry."), N_("USERNAME"), ARG_TYPE_STRING},
{"hotkey", 3, 0,
N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING},
N_("Keyboard key for this entry."), N_("KEY"), ARG_TYPE_STRING},
{"source", 4, 0,
N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING},
N_("Menu entry definition as a string."), N_("STRING"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
static struct
{
char *name;
const char *name;
int key;
} hotkey_aliases[] =
{

View file

@ -145,7 +145,7 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
{
grub_dl_t mod;
grub_printf ("Name\tRef Count\tDependencies\n");
grub_printf_ (N_("Name\tRef Count\tDependencies\n"));
FOR_DL_MODULES (mod)
{
grub_dl_dep_t dep;
@ -165,13 +165,13 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
}
/* exit */
static grub_err_t
static grub_err_t __attribute__ ((noreturn))
grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
grub_exit ();
return 0;
/* Not reached. */
}
static grub_command_t cmd_cat, cmd_help;

View file

@ -23,6 +23,7 @@
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/cs5536.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -38,43 +39,44 @@ grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
if (!grub_cs5536_find (&dev))
{
grub_printf ("No CS5536 found\n");
grub_puts_ (N_("No CS5536 found"));
return GRUB_ERR_NONE;
}
grub_printf ("CS5536 at %d:%d.%d\n", grub_pci_get_bus (dev),
grub_pci_get_device (dev), grub_pci_get_function (dev));
grub_printf_ (N_("CS5536 at %d:%d.%d\n"), grub_pci_get_bus (dev),
grub_pci_get_device (dev), grub_pci_get_function (dev));
err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase);
if (err)
return err;
grub_printf ("SMB base = 0x%x\n", smbbase);
grub_printf_ (N_("SMB base = 0x%x\n"), smbbase);
for (i = GRUB_SMB_RAM_START_ADDR;
i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
{
struct grub_smbus_spd spd;
grub_memset (&spd, 0, sizeof (spd));
grub_printf ("Device %d\n", i);
grub_printf_ (N_("Device %d\n"), i);
err = grub_cs5536_read_spd (smbbase, i, &spd);
if (err)
{
grub_print_error ();
continue;
}
grub_printf ("Written SPD bytes: %d B.\n", spd.written_size);
grub_printf ("Total flash size: %d B.\n", 1 << spd.log_total_flash_size);
grub_printf_ (N_("Written SPD bytes: %d B.\n"), spd.written_size);
grub_printf_ (N_("Total flash size: %d B.\n"),
1 << spd.log_total_flash_size);
if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2)
{
char str[sizeof (spd.ddr2.part_number) + 1];
grub_printf ("Memory type: DDR2.\n");
grub_puts_ (N_("Memory type: DDR2."));
grub_memcpy (str, spd.ddr2.part_number,
sizeof (spd.ddr2.part_number));
str[sizeof (spd.ddr2.part_number)] = 0;
grub_printf ("Part no: %s.\n", str);
grub_printf_ (N_("Part no: %s.\n"), str);
}
else
grub_printf ("Memory type: Unknown.\n");
grub_puts_ (N_("Memory type: Unknown."));
}
return GRUB_ERR_NONE;
@ -85,7 +87,7 @@ static grub_command_t cmd;
GRUB_MOD_INIT(lsspd)
{
cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0,
"Print Memory information.");
N_("Print Memory information."));
}
GRUB_MOD_FINI(lsspd)

View file

@ -37,9 +37,9 @@ static struct grub_parttool *parts = 0;
static int curhandle = 0;
static grub_dl_t mymod;
static char helpmsg[] =
"Perform COMMANDS on partition.\n"
"Use \"parttool PARTITION help\" for the list "
"of available commands.";
N_("Perform COMMANDS on partition.\n"
"Use \"parttool PARTITION help\" for the list "
"of available commands.");
int
grub_parttool_register(const char *part_name,
@ -128,7 +128,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
break;
case GRUB_PARTTOOL_ARG_VAL:
grub_printf ("=VAL");
grub_xputs (_("=VAL"));
spacing -= 4;
break;
@ -137,18 +137,18 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
}
while (spacing-- > 0)
grub_printf (" ");
grub_printf ("%s\n", curarg->desc);
grub_puts_ (curarg->desc);
}
}
if (! found)
grub_printf ("Sorry no parttool is available for %s\n",
grub_printf_ (N_("Sorry no parttool is available for %s\n"),
dev->disk->partition->partmap->name);
return GRUB_ERR_NONE;
}
if (argc < 1)
{
grub_printf ("%s\n", helpmsg);
grub_puts_ (helpmsg);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments");
}

View file

@ -136,7 +136,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
return err;
if (! label)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"uuid for this FS isn't supported yet");
"label for this FS isn't supported yet");
if (state[0].set)
grub_env_set (state[0].arg, label);

View file

@ -24,13 +24,12 @@
GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t
static grub_err_t __attribute__ ((noreturn))
grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
grub_reboot ();
return 0;
}
static grub_command_t cmd;

View file

@ -33,11 +33,21 @@
GRUB_MOD_LICENSE ("GPLv3+");
struct cache_entry
{
struct cache_entry *next;
char *key;
char *value;
};
static struct cache_entry *cache;
void
FUNC_NAME (const char *key, const char *var, int no_floppy,
char **hints, unsigned nhints)
{
int count = 0;
int is_cache = 0;
grub_fs_autoload_hook_t saved_autoload;
auto int iterate_device (const char *name);
@ -50,6 +60,12 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
return 0;
#ifdef DO_SEARCH_FS_UUID
#define compare_fn grub_strcasecmp
#else
#define compare_fn grub_strcmp
#endif
#ifdef DO_SEARCH_FILE
{
char *buf;
@ -81,10 +97,8 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
fs = grub_fs_probe (dev);
#ifdef DO_SEARCH_FS_UUID
#define compare_fn grub_strcasecmp
#define read_fn uuid
#else
#define compare_fn grub_strcmp
#define read_fn label
#endif
@ -106,6 +120,31 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
}
#endif
if (!is_cache && found && count == 0)
{
struct cache_entry *cache_ent;
cache_ent = grub_malloc (sizeof (*cache_ent));
if (cache_ent)
{
cache_ent->key = grub_strdup (key);
cache_ent->value = grub_strdup (name);
if (cache_ent->value && cache_ent->key)
{
cache_ent->next = cache;
cache = cache_ent;
}
else
{
grub_free (cache_ent->value);
grub_free (cache_ent->key);
grub_free (cache_ent);
grub_errno = GRUB_ERR_NONE;
}
}
else
grub_errno = GRUB_ERR_NONE;
}
if (found)
{
count++;
@ -143,6 +182,32 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
void try (void)
{
unsigned i;
struct cache_entry **prev;
struct cache_entry *cache_ent;
for (prev = &cache, cache_ent = *prev; cache_ent;
prev = &cache_ent->next, cache_ent = *prev)
if (compare_fn (cache_ent->key, key) == 0)
break;
if (cache_ent)
{
is_cache = 1;
if (iterate_device (cache_ent->value))
{
is_cache = 0;
return;
}
is_cache = 0;
/* Cache entry was outdated. Remove it. */
if (!count)
{
grub_free (cache_ent->key);
grub_free (cache_ent->value);
grub_free (cache_ent);
*prev = cache_ent->next;
}
}
for (i = 0; i < nhints; i++)
{
char *end;
@ -164,17 +229,20 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
dev = grub_device_open (hints[i]);
if (!dev)
{
*end = ',';
if (!*end)
*end = ',';
continue;
}
if (!dev->disk)
{
grub_device_close (dev);
*end = ',';
if (!*end)
*end = ',';
continue;
}
ret = grub_partition_iterate (dev->disk, part_hook);
*end = ',';
if (!*end)
*end = ',';
grub_device_close (dev);
if (ret)
return;

View file

@ -42,6 +42,21 @@ static const struct grub_arg_option options[] =
{"hint", 'h', GRUB_ARG_OPTION_REPEATABLE,
N_("First try the device HINT. If HINT ends in comma, "
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
{"hint-ieee1275", 0, GRUB_ARG_OPTION_REPEATABLE,
N_("First try the device HINT if on IEEE1275. If HINT ends in comma, "
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
{"hint-bios", 0, GRUB_ARG_OPTION_REPEATABLE,
N_("First try the device HINT if on BIOS. If HINT ends in comma, "
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
{"hint-baremetal", 0, GRUB_ARG_OPTION_REPEATABLE,
N_("First try the device HINT. If HINT ends in comma, "
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
{"hint-efi", 0, GRUB_ARG_OPTION_REPEATABLE,
N_("First try the device HINT if on EFI. If HINT ends in comma, "
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
{"hint-arc", 0, GRUB_ARG_OPTION_REPEATABLE,
N_("First try the device HINT if on ARC. If HINT ends in comma, "
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@ -52,7 +67,12 @@ enum options
SEARCH_FS_UUID,
SEARCH_SET,
SEARCH_NO_FLOPPY,
SEARCH_HINT
SEARCH_HINT,
SEARCH_HINT_IEEE1275,
SEARCH_HINT_BIOS,
SEARCH_HINT_BAREMETAL,
SEARCH_HINT_EFI,
SEARCH_HINT_ARC,
};
static grub_err_t
@ -60,27 +80,98 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
const char *var = 0;
int nhints = 0;
int i = 0, j = 0, nhints = 0;
char **hints = NULL;
if (state[SEARCH_HINT].set)
while (state[SEARCH_HINT].args[nhints])
for (i = 0; state[SEARCH_HINT].args[i]; i++)
nhints++;
if (argc == 0)
#ifdef GRUB_MACHINE_IEEE1275
if (state[SEARCH_HINT_IEEE1275].set)
for (i = 0; state[SEARCH_HINT_IEEE1275].args[i]; i++)
nhints++;
#endif
#ifdef GRUB_MACHINE_EFI
if (state[SEARCH_HINT_EFI].set)
for (i = 0; state[SEARCH_HINT_EFI].args[i]; i++)
nhints++;
#endif
#ifdef GRUB_MACHINE_PCBIOS
if (state[SEARCH_HINT_BIOS].set)
for (i = 0; state[SEARCH_HINT_BIOS].args[i]; i++)
nhints++;
#endif
#ifdef GRUB_MACHINE_ARC
if (state[SEARCH_HINT_ARC].set)
for (i = 0; state[SEARCH_HINT_ARC].args[i]; i++)
nhints++;
#endif
if (state[SEARCH_HINT_BAREMETAL].set)
for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++)
nhints++;
hints = grub_malloc (sizeof (hints[0]) * nhints);
if (!hints)
return grub_errno;
j = 0;
if (state[SEARCH_HINT].set)
for (i = 0; state[SEARCH_HINT].args[i]; i++)
hints[j++] = state[SEARCH_HINT].args[i];
#ifdef GRUB_MACHINE_IEEE1275
if (state[SEARCH_HINT_IEEE1275].set)
for (i = 0; state[SEARCH_HINT_IEEE1275].args[i]; i++)
hints[j++] = state[SEARCH_HINT_IEEE1275].args[i];
#endif
#ifdef GRUB_MACHINE_EFI
if (state[SEARCH_HINT_EFI].set)
for (i = 0; state[SEARCH_HINT_EFI].args[i]; i++)
hints[j++] = state[SEARCH_HINT_EFI].args[i];
#endif
#ifdef GRUB_MACHINE_ARC
if (state[SEARCH_HINT_ARC].set)
for (i = 0; state[SEARCH_HINT_ARC].args[i]; i++)
hints[j++] = state[SEARCH_HINT_ARC].args[i];
#endif
#ifdef GRUB_MACHINE_PCBIOS
if (state[SEARCH_HINT_BIOS].set)
for (i = 0; state[SEARCH_HINT_BIOS].args[i]; i++)
hints[j++] = state[SEARCH_HINT_BIOS].args[i];
#endif
if (state[SEARCH_HINT_BAREMETAL].set)
for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++)
hints[j++] = state[SEARCH_HINT_BAREMETAL].args[i];
/* Skip hints for future platforms. */
for (j = 0; j < argc; j++)
if (grub_memcmp (args[j], "--hint-", sizeof ("--hint-") - 1) != 0)
break;
if (argc == j)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
if (state[SEARCH_SET].set)
var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root";
if (state[SEARCH_LABEL].set)
grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set,
state[SEARCH_HINT].args, nhints);
grub_search_label (args[j], var, state[SEARCH_NO_FLOPPY].set,
hints, nhints);
else if (state[SEARCH_FS_UUID].set)
grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set,
state[SEARCH_HINT].args, nhints);
grub_search_fs_uuid (args[j], var, state[SEARCH_NO_FLOPPY].set,
hints, nhints);
else if (state[SEARCH_FILE].set)
grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set,
state[SEARCH_HINT].args, nhints);
grub_search_fs_file (args[j], var, state[SEARCH_NO_FLOPPY].set,
hints, nhints);
else
return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
@ -92,7 +183,8 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(search)
{
cmd =
grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_EXTRACTOR,
grub_register_extcmd ("search", grub_cmd_search,
GRUB_COMMAND_FLAG_EXTRACTOR | GRUB_COMMAND_ACCEPT_DASH,
N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]"
" NAME"),
N_("Search devices by file, filesystem label"

View file

@ -66,12 +66,12 @@ static struct pci_register pci_registers[] =
static const struct grub_arg_option options[] =
{
{0, 'd', 0, "Select device by vendor and device IDs.",
"[vendor]:[device]", ARG_TYPE_STRING},
{0, 's', 0, "Select device by its position on the bus.",
"[bus]:[slot][.func]", ARG_TYPE_STRING},
{0, 'v', 0, "Save read value into variable VARNAME.",
"VARNAME", ARG_TYPE_STRING},
{0, 'd', 0, N_("Select device by vendor and device IDs."),
N_("[vendor]:[device]"), ARG_TYPE_STRING},
{0, 's', 0, N_("Select device by its position on the bus."),
N_("[bus]:[slot][.func]"), ARG_TYPE_STRING},
{0, 'v', 0, N_("Save read value into variable VARNAME."),
N_("VARNAME"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@ -128,7 +128,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
if (!write_mask)
{
grub_printf ("Register %x of %d:%d.%d is %x\n", regaddr,
grub_printf (N_("Register %x of %d:%d.%d is %x\n"), regaddr,
grub_pci_get_bus (dev),
grub_pci_get_device (dev),
grub_pci_get_function (dev),

View file

@ -31,6 +31,7 @@ struct grub_term_autoload *grub_term_output_autoload = NULL;
struct abstract_terminal
{
struct abstract_terminal *next;
struct abstract_terminal *prev;
const char *name;
grub_err_t (*init) (struct abstract_terminal *term);
grub_err_t (*fini) (struct abstract_terminal *term);
@ -94,11 +95,15 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
while (1)
{
for (term = *disabled; term; term = term->next)
if (grub_strcmp (args[i], term->name) == 0)
if (grub_strcmp (args[i], term->name) == 0
|| (grub_strcmp (args[i], "ofconsole") == 0
&& grub_strcmp ("console", term->name) == 0))
break;
if (term == 0)
for (term = *enabled; term; term = term->next)
if (grub_strcmp (args[i], term->name) == 0)
if (grub_strcmp (args[i], term->name) == 0
|| (grub_strcmp (args[i], "ofconsole") == 0
&& grub_strcmp ("console", term->name) == 0))
break;
if (term)
break;
@ -107,6 +112,8 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
args[i]);
for (aut = autoloads; aut; aut = aut->next)
if (grub_strcmp (args[i], aut->name) == 0
|| (grub_strcmp (args[i], "ofconsole") == 0
&& grub_strcmp ("console", aut->name) == 0)
|| (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*'
&& grub_memcmp (args[i], aut->name,
grub_strlen (aut->name) - 1) == 0))
@ -130,14 +137,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
for (i = 1; i < argc; i++)
{
for (term = *disabled; term; term = term->next)
if (grub_strcmp (args[i], term->name) == 0)
if (grub_strcmp (args[i], term->name) == 0
|| (grub_strcmp (args[i], "ofconsole") == 0
&& grub_strcmp ("console", term->name) == 0))
break;
if (term)
{
if (term->init && term->init (term) != GRUB_ERR_NONE)
return grub_errno;
grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
grub_list_remove (GRUB_AS_LIST (term));
grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
}
}
@ -149,14 +158,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
for (i = 1; i < argc; i++)
{
for (term = *enabled; term; term = term->next)
if (grub_strcmp (args[i], term->name) == 0)
if (grub_strcmp (args[i], term->name) == 0
|| (grub_strcmp (args[i], "ofconsole") == 0
&& grub_strcmp ("console", term->name) == 0))
break;
if (term)
{
if (!term->next && term == *enabled)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
grub_list_remove (GRUB_AS_LIST (term));
if (term->fini)
term->fini (term);
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
@ -167,14 +178,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
for (i = 0; i < argc; i++)
{
for (term = *disabled; term; term = term->next)
if (grub_strcmp (args[i], term->name) == 0)
if (grub_strcmp (args[i], term->name) == 0
|| (grub_strcmp (args[i], "ofconsole") == 0
&& grub_strcmp ("console", term->name) == 0))
break;
if (term)
{
if (term->init && term->init (term) != GRUB_ERR_NONE)
return grub_errno;
grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
grub_list_remove (GRUB_AS_LIST (term));
grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
}
}
@ -185,14 +198,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
{
next = term->next;
for (i = 0; i < argc; i++)
if (grub_strcmp (args[i], term->name) == 0)
if (grub_strcmp (args[i], term->name) == 0
|| (grub_strcmp (args[i], "ofconsole") == 0
&& grub_strcmp ("console", term->name) == 0))
break;
if (i == argc)
{
if (!term->next && term == *enabled)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
grub_list_remove (GRUB_AS_LIST (term));
if (term->fini)
term->fini (term);
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
@ -208,6 +223,7 @@ grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, next);
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, prev);
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, name);
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init);
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini);
@ -224,6 +240,7 @@ grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, next);
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, prev);
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, name);
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, init);
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, fini);

View file

@ -47,8 +47,8 @@ grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)),
(cmd->func) (cmd, argc - 1, &args[1]);
end = grub_get_time_ms ();
grub_printf ("Elapsed time: %d.%03d seconds \n", (end - start) / 1000,
(end - start) % 1000);
grub_printf_ (N_("Elapsed time: %d.%03d seconds \n"), (end - start) / 1000,
(end - start) % 1000);
return grub_errno;
}

View file

@ -52,36 +52,36 @@ hook (const struct grub_video_mode_info *info)
grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp);
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
grub_printf ("Text-only ");
grub_xputs (_("Text-only "));
/* Show mask and position details for direct color modes. */
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB)
grub_printf ("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d",
info->red_mask_size,
info->green_mask_size,
info->blue_mask_size,
info->reserved_mask_size,
info->red_field_pos,
info->green_field_pos,
info->blue_field_pos,
info->reserved_field_pos);
grub_printf_ (N_("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d"),
info->red_mask_size,
info->green_mask_size,
info->blue_mask_size,
info->reserved_mask_size,
info->red_field_pos,
info->green_field_pos,
info->blue_field_pos,
info->reserved_field_pos);
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
grub_printf ("Packed ");
grub_xputs (_("Packed "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV)
grub_printf ("YUV ");
grub_xputs (_("YUV "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR)
grub_printf ("Planar ");
grub_xputs (_("Planar "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES)
grub_printf ("Hercules ");
grub_xputs (_("Hercules "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA)
grub_printf ("CGA ");
grub_xputs (_("CGA "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4)
grub_printf ("Non-chain 4 ");
grub_xputs (_("Non-chain 4 "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP)
grub_printf ("Monochrome ");
grub_xputs (_("Monochrome "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN)
grub_printf ("Unknown ");
grub_xputs (_("Unknown "));
grub_printf ("\n");
grub_xputs ("\n");
return 0;
}
@ -93,19 +93,19 @@ print_edid (struct grub_video_edid_info *edid_info)
if (grub_video_edid_checksum (edid_info))
{
grub_printf (" EDID checksum invalid\n");
grub_puts_ (N_(" EDID checksum invalid"));
grub_errno = GRUB_ERR_NONE;
return;
}
grub_printf (" EDID version: %u.%u\n",
edid_info->version, edid_info->revision);
grub_printf_ (N_(" EDID version: %u.%u\n"),
edid_info->version, edid_info->revision);
if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height)
== GRUB_ERR_NONE)
grub_printf (" Preferred mode: %ux%u\n", edid_width, edid_height);
grub_printf_ (N_(" Preferred mode: %ux%u\n"), edid_width, edid_height);
else
{
grub_printf (" No preferred mode available\n");
grub_printf_ (N_(" No preferred mode available\n"));
grub_errno = GRUB_ERR_NONE;
}
}
@ -147,20 +147,20 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
id = grub_video_get_driver_id ();
grub_printf ("List of supported video modes:\n");
grub_printf ("Legend: P=Packed pixel, D=Direct color, "
"mask/pos=R/G/B/reserved\n");
grub_puts_ (N_("List of supported video modes:"));
grub_puts_ (N_("Legend: P=Packed pixel, D=Direct color, "
"mask/pos=R/G/B/reserved"));
FOR_VIDEO_ADAPTERS (adapter)
{
struct grub_video_mode_info info;
struct grub_video_edid_info edid_info;
grub_printf ("Adapter '%s':\n", adapter->name);
grub_printf_ (N_("Adapter '%s':\n"), adapter->name);
if (!adapter->iterate)
{
grub_printf (" No info available\n");
grub_puts_ (N_(" No info available"));
continue;
}
@ -178,7 +178,7 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
{
if (adapter->init ())
{
grub_printf (" Failed\n");
grub_puts_ (N_(" Failed"));
grub_errno = GRUB_ERR_NONE;
continue;
}
@ -215,12 +215,13 @@ static grub_command_t cmd_vbe;
GRUB_MOD_INIT(videoinfo)
{
cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, "[WxH[xD]]",
cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, N_("[WxH[xD]]"),
N_("List available video modes. If "
"resolution is given show only modes"
" matching it."));
#ifdef GRUB_MACHINE_PCBIOS
cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, "[WxH[xD]]",
cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo,
N_("[WxH[xD]]"),
N_("List available video modes. If "
"resolution is given show only modes"
" matching it."));

View file

@ -74,6 +74,8 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
grub_video_create_render_target (&text_layer, width, height,
GRUB_VIDEO_MODE_TYPE_RGB
| GRUB_VIDEO_MODE_TYPE_ALPHA);
if (!text_layer)
goto fail;
grub_video_set_active_render_target (text_layer);
@ -191,6 +193,11 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
grub_errno = GRUB_ERR_NONE;
return grub_errno;
fail:
grub_video_delete_render_target (text_layer);
grub_video_restore ();
return grub_errno;
}
static grub_command_t cmd;

View file

@ -326,10 +326,15 @@ match_files (const char *prefix, const char *suffix, const char *end,
if (! fs)
goto fail;
path = grub_strchr (dir, ')');
if (! path)
goto fail;
path++;
if (dir[0] == '(')
{
path = grub_strchr (dir, ')');
if (!path)
goto fail;
path++;
}
else
path = dir;
if (fs->dir (dev, path, match))
goto fail;
@ -431,25 +436,8 @@ wildcard_expand (const char *s, char ***strs)
if (start == noregexop) /* device part has regexop */
paths = match_devices (&regexp, *start != '(');
else if (*start == '(') /* device part explicit wo regexop */
else /* device part explicit wo regexop */
paths = match_files ("", start, noregexop, &regexp);
else if (*start == '/') /* no device part */
{
char *root;
char *prefix;
root = grub_env_get ("root");
if (! root)
goto fail;
prefix = grub_xasprintf ("(%s)", root);
if (! prefix)
goto fail;
paths = match_files (prefix, start, noregexop, &regexp);
grub_free (prefix);
}
}
else
{

View file

@ -51,10 +51,18 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
char *ptr;
grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
int low = 0;
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required");
if (argc > 1 && grub_strcmp (args[0], "-l") == 0)
{
low = 1;
argc--;
args++;
}
serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
GRUB_MD_MD5->init (&ctx);
@ -75,10 +83,11 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
(unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11],
(unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13],
(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
for (ptr = uuid_string; *ptr; ptr++)
*ptr = grub_toupper (*ptr);
if (!low)
for (ptr = uuid_string; *ptr; ptr++)
*ptr = grub_toupper (*ptr);
if (argc == 1)
grub_printf ("%s", uuid_string);
grub_printf ("%s\n", uuid_string);
if (argc > 1)
grub_env_set (args[1], uuid_string);
@ -91,9 +100,10 @@ static grub_command_t cmd;
GRUB_MOD_INIT (xnu_uuid)
{
cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid,
N_("GRUBUUID [VARNAME]"),
N_("[-l] GRUBUUID [VARNAME]"),
N_("Transform 64-bit UUID to format "
"suitable for XNU."));
"suitable for XNU. If -l is given keep "
"it lowercase as done by blkid."));
}
GRUB_MOD_FINI (xnu_uuid)

View file

@ -121,6 +121,7 @@ enum
struct grub_ahci_device
{
struct grub_ahci_device *next;
struct grub_ahci_device **prev;
volatile struct grub_ahci_hba *hba;
int port;
int num;
@ -305,7 +306,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
else
grub_dprintf ("ahci", "AHCI is already in OS mode\n");
if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN))
if (!(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN))
grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n");
else
grub_dprintf ("ahci", "AHCI is in AHCI mode.\n");
@ -692,6 +693,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata)
ata->data = dev;
ata->dma = 1;
ata->maxbuffer = GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH;
ata->present = &dev->present;
return GRUB_ERR_NONE;
@ -706,7 +708,7 @@ static struct grub_ata_dev grub_ahci_dev =
static void *fini_hnd;
static struct grub_preboot *fini_hnd;
GRUB_MOD_INIT(ahci)
{

View file

@ -24,6 +24,7 @@
static grub_arc_fileno_t last_handle = 0;
static char *last_path = NULL;
static int handle_writable = 0;
static int lnum = 0;
@ -100,11 +101,12 @@ grub_arcdisk_iterate (int (*hook_in) (const char *name),
#define RAW_SUFFIX "partition(10)"
static grub_err_t
reopen (const char *name)
reopen (const char *name, int writable)
{
grub_arc_fileno_t handle;
if (last_path && grub_strcmp (last_path, name) == 0)
if (last_path && grub_strcmp (last_path, name) == 0
&& (!writable || handle_writable))
{
grub_dprintf ("arcdisk", "using already opened %s\n", name);
return GRUB_ERR_NONE;
@ -115,12 +117,16 @@ reopen (const char *name)
grub_free (last_path);
last_path = NULL;
last_handle = 0;
handle_writable = 0;
}
if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle))
if (GRUB_ARC_FIRMWARE_VECTOR->open (name,
writable ? GRUB_ARC_FILE_ACCESS_OPEN_RW
: GRUB_ARC_FILE_ACCESS_OPEN_RO, &handle))
{
grub_dprintf ("arcdisk", "couldn't open %s\n", name);
return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
}
handle_writable = writable;
last_path = grub_strdup (name);
if (!last_path)
return grub_errno;
@ -180,7 +186,7 @@ grub_arcdisk_open (const char *name, grub_disk_t disk)
if (!hash)
return grub_errno;
err = reopen (fullname);
err = reopen (fullname, 0);
if (err)
return err;
@ -234,7 +240,7 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_uint64_t totl = size << 9;
grub_arc_err_t r;
err = reopen (disk->data);
err = reopen (disk->data, 0);
if (err)
return err;
r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
@ -258,12 +264,36 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
}
static grub_err_t
grub_arcdisk_write (grub_disk_t disk __attribute ((unused)),
grub_disk_addr_t sector __attribute ((unused)),
grub_size_t size __attribute ((unused)),
const char *buf __attribute ((unused)))
grub_arcdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, const char *buf)
{
return GRUB_ERR_NOT_IMPLEMENTED_YET;
grub_err_t err;
grub_uint64_t pos = sector << 9;
unsigned long count;
grub_uint64_t totl = size << 9;
grub_arc_err_t r;
err = reopen (disk->data, 1);
if (err)
return err;
r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
if (r)
{
grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %ld\n",
pos, r);
return grub_error (GRUB_ERR_IO, "couldn't seek");
}
while (totl)
{
if (GRUB_ARC_FIRMWARE_VECTOR->write (last_handle, buf,
totl, &count))
return grub_error (GRUB_ERR_WRITE_ERROR, "write failed");
totl -= count;
buf += count;
}
return GRUB_ERR_NONE;
}
static struct grub_disk_dev grub_arcdisk_dev =

View file

@ -29,29 +29,27 @@ static grub_ata_dev_t grub_ata_dev_list;
/* Byteorder has to be changed before strings can be read. */
static void
grub_ata_strncpy (char *dst, char *src, grub_size_t len)
grub_ata_strncpy (grub_uint16_t *dst16, grub_uint16_t *src16, grub_size_t len)
{
grub_uint16_t *src16 = (grub_uint16_t *) src;
grub_uint16_t *dst16 = (grub_uint16_t *) dst;
unsigned int i;
for (i = 0; i < len / 2; i++)
*(dst16++) = grub_be_to_cpu16 (*(src16++));
dst[len] = '\0';
dst16[i] = 0;
}
static void
grub_ata_dumpinfo (struct grub_ata *dev, char *info)
grub_ata_dumpinfo (struct grub_ata *dev, grub_uint16_t *info)
{
char text[41];
grub_uint16_t text[21];
/* The device information was read, dump it for debugging. */
grub_ata_strncpy (text, info + 20, 20);
grub_dprintf ("ata", "Serial: %s\n", text);
grub_ata_strncpy (text, info + 46, 8);
grub_dprintf ("ata", "Firmware: %s\n", text);
grub_ata_strncpy (text, info + 54, 40);
grub_dprintf ("ata", "Model: %s\n", text);
grub_ata_strncpy (text, info + 10, 20);
grub_dprintf ("ata", "Serial: %s\n", (char *) text);
grub_ata_strncpy (text, info + 23, 8);
grub_dprintf ("ata", "Firmware: %s\n", (char *) text);
grub_ata_strncpy (text, info + 27, 40);
grub_dprintf ("ata", "Model: %s\n", (char *) text);
if (! dev->atapi)
{
@ -65,7 +63,7 @@ static grub_err_t
grub_atapi_identify (struct grub_ata *dev)
{
struct grub_disk_ata_pass_through_parms parms;
char *info;
grub_uint16_t *info;
grub_err_t err;
info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
@ -105,17 +103,19 @@ static grub_err_t
grub_ata_identify (struct grub_ata *dev)
{
struct grub_disk_ata_pass_through_parms parms;
char *info;
grub_uint64_t *info64;
grub_uint32_t *info32;
grub_uint16_t *info16;
grub_err_t err;
info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
if (! info)
info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE);
info32 = (grub_uint32_t *) info64;
info16 = (grub_uint16_t *) info64;
if (! info16)
return grub_errno;
info16 = (grub_uint16_t *) info;
grub_memset (&parms, 0, sizeof (parms));
parms.buffer = info;
parms.buffer = info16;
parms.size = GRUB_DISK_SECTOR_SIZE;
parms.taskfile.disk = 0xE0;
@ -126,7 +126,7 @@ grub_ata_identify (struct grub_ata *dev)
if (err || parms.size != GRUB_DISK_SECTOR_SIZE)
{
grub_uint8_t sts = parms.taskfile.status;
grub_free (info);
grub_free (info16);
grub_errno = GRUB_ERR_NONE;
if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ
| GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR
@ -167,14 +167,14 @@ grub_ata_identify (struct grub_ata *dev)
/* Determine the amount of sectors. */
if (dev->addr != GRUB_ATA_LBA48)
dev->size = grub_le_to_cpu32(*((grub_uint32_t *) &info16[60]));
dev->size = grub_le_to_cpu32 (info32[30]);
else
dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100]));
dev->size = grub_le_to_cpu64 (info64[25]);
if (info16[106] & (1 << 12))
{
grub_uint32_t secsize;
secsize = grub_le_to_cpu32 (*((grub_uint32_t *) &info16[117]));
secsize = grub_le_to_cpu32 (grub_get_unaligned32 (&info16[117]));
if (secsize & (secsize - 1) || !secsize
|| secsize > 1048576)
secsize = 256;
@ -191,9 +191,9 @@ grub_ata_identify (struct grub_ata *dev)
dev->heads = info16[3];
dev->sectors_per_track = info16[6];
grub_ata_dumpinfo (dev, info);
grub_ata_dumpinfo (dev, info16);
grub_free(info);
grub_free (info16);
return 0;
}
@ -278,6 +278,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
grub_ata_addressing_t addressing = ata->addr;
grub_size_t batch;
int cmd, cmd_write;
grub_size_t nsectors = 0;
grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n",
(unsigned long long) size, rw);
@ -314,9 +315,11 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
cmd = GRUB_ATA_CMD_READ_SECTORS;
cmd_write = GRUB_ATA_CMD_WRITE_SECTORS;
}
}
}
if (batch > (ata->maxbuffer >> ata->log_sector_size))
batch = (ata->maxbuffer >> ata->log_sector_size);
grub_size_t nsectors = 0;
while (nsectors < size)
{
struct grub_disk_ata_pass_through_parms parms;
@ -534,7 +537,7 @@ grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)),
grub_size_t cmdsize __attribute__((unused)),
char *cmd __attribute__((unused)),
grub_size_t size __attribute__((unused)),
char *buf __attribute__((unused)))
const char *buf __attribute__((unused)))
{
// XXX: scsi.mod does not use write yet.
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not implemented");

View file

@ -128,6 +128,29 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
return GPG_ERR_NO_ERROR;
}
static gcry_err_code_t
grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size,
void *iv)
{
grub_uint8_t *inptr, *outptr, *end;
grub_uint8_t ivt[cipher->cipher->blocksize];
if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0)
return GPG_ERR_INV_ARG;
end = (grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
{
grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
}
return GPG_ERR_NO_ERROR;
}
struct lrw_sector
{
grub_uint8_t low[GRUB_CRYPTODISK_GF_BYTES];
@ -189,17 +212,18 @@ lrw_xor (const struct lrw_sector *sec,
dev->lrw_precalc, sec->low_byte * GRUB_CRYPTODISK_GF_BYTES);
}
gcry_err_code_t
grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
grub_uint8_t * data, grub_size_t len,
grub_disk_addr_t sector)
static gcry_err_code_t
grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
grub_uint8_t * data, grub_size_t len,
grub_disk_addr_t sector, int encrypt)
{
grub_size_t i;
gcry_err_code_t err;
/* The only mode without IV. */
if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey)
return grub_crypto_ecb_decrypt (dev->cipher, data, data, len);
return (encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
: grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
for (i = 0; i < len; i += (1U << dev->log_sector_size))
{
@ -269,15 +293,23 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
switch (dev->mode)
{
case GRUB_CRYPTODISK_MODE_CBC:
err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size), iv);
if (encrypt)
err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size), iv);
else
err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size), iv);
if (err)
return err;
break;
case GRUB_CRYPTODISK_MODE_PCBC:
err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size), iv);
if (encrypt)
err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size), iv);
else
err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size), iv);
if (err)
return err;
break;
@ -294,9 +326,14 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
{
grub_crypto_xor (data + i + j, data + i + j, iv,
dev->cipher->cipher->blocksize);
err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j,
data + i + j,
dev->cipher->cipher->blocksize);
if (encrypt)
err = grub_crypto_ecb_encrypt (dev->cipher, data + i + j,
data + i + j,
dev->cipher->cipher->blocksize);
else
err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j,
data + i + j,
dev->cipher->cipher->blocksize);
if (err)
return err;
grub_crypto_xor (data + i + j, data + i + j, iv,
@ -312,17 +349,26 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv);
lrw_xor (&sec, dev, data + i);
err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
data + i,
(1U << dev->log_sector_size));
if (encrypt)
err = grub_crypto_ecb_encrypt (dev->cipher, data + i,
data + i,
(1U << dev->log_sector_size));
else
err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
data + i,
(1U << dev->log_sector_size));
if (err)
return err;
lrw_xor (&sec, dev, data + i);
}
break;
case GRUB_CRYPTODISK_MODE_ECB:
grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size));
if (encrypt)
grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size));
else
grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size));
break;
default:
return GPG_ERR_NOT_IMPLEMENTED;
@ -332,6 +378,14 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
grub_uint8_t * data, grub_size_t len,
grub_disk_addr_t sector)
{
return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
}
gcry_err_code_t
grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize)
{
@ -526,19 +580,61 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err);
return err;
}
gcry_err = grub_cryptodisk_decrypt (dev, (grub_uint8_t *) buf,
size << disk->log_sector_size,
sector);
gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
size << disk->log_sector_size,
sector, 0);
return grub_crypto_gcry_error (gcry_err);
}
static grub_err_t
grub_cryptodisk_write (grub_disk_t disk __attribute ((unused)),
grub_disk_addr_t sector __attribute ((unused)),
grub_size_t size __attribute ((unused)),
const char *buf __attribute ((unused)))
grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, const char *buf)
{
return GRUB_ERR_NOT_IMPLEMENTED_YET;
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
gcry_err_code_t gcry_err;
char *tmp;
grub_err_t err;
#ifdef GRUB_UTIL
if (dev->cheat)
{
err = grub_util_fd_seek (dev->cheat_fd, dev->cheat,
sector << disk->log_sector_size);
if (err)
return err;
if (grub_util_fd_write (dev->cheat_fd, buf, size << disk->log_sector_size)
!= (ssize_t) (size << disk->log_sector_size))
return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'",
dev->cheat);
return GRUB_ERR_NONE;
}
#endif
tmp = grub_malloc (size << disk->log_sector_size);
if (!tmp)
return grub_errno;
grub_memcpy (tmp, buf, size << disk->log_sector_size);
grub_dprintf ("cryptodisk",
"Writing %" PRIuGRUB_SIZE " sectors to sector 0x%"
PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
size, sector, dev->offset);
gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
size << disk->log_sector_size,
sector, 1);
if (gcry_err)
{
grub_free (tmp);
return grub_crypto_gcry_error (gcry_err);
}
err = grub_disk_write (dev->source_disk,
(sector << (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS)) + dev->offset,
0, size << disk->log_sector_size, tmp);
grub_free (tmp);
return err;
}
#ifdef GRUB_UTIL
@ -562,6 +658,7 @@ grub_cryptodisk_memberlist (grub_disk_t disk)
static void
cryptodisk_cleanup (void)
{
#if 0
grub_cryptodisk_t dev = cryptodisk_list;
grub_cryptodisk_t tmp;
@ -575,6 +672,7 @@ cryptodisk_cleanup (void)
grub_free (dev);
dev = tmp;
}
#endif
}
grub_err_t

1081
grub-core/disk/diskfilter.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,7 @@
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
#include <grub/diskfilter.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -90,70 +90,91 @@ struct grub_nv_super
struct grub_nv_array array; /* Array information */
} __attribute__ ((packed));
static grub_err_t
grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
static struct grub_diskfilter_vg *
grub_dmraid_nv_detect (grub_disk_t disk,
struct grub_diskfilter_pv_id *id,
grub_disk_addr_t *start_sector)
{
grub_disk_addr_t sector;
struct grub_nv_super sb;
int level;
int layout;
grub_uint64_t disk_size;
char *uuid;
if (disk->partition)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition");
sector = grub_disk_get_size (disk) - 2;
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition");
return NULL;
}
sector = grub_disk_get_size (disk);
if (sector == GRUB_DISK_SIZE_UNKNOWN)
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
return NULL;
}
sector -= 2;
if (grub_disk_read (disk, sector, 0, sizeof (sb), &sb))
return grub_errno;
return NULL;
if (grub_memcmp (sb.vendor, NV_ID_STRING, 6))
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
return NULL;
}
if (sb.version != NV_VERSION)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unknown version: %d.%d", sb.version);
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unknown version: %d.%d", sb.version);
return NULL;
}
switch (sb.array.raid_level)
{
case NV_LEVEL_0:
array->level = 0;
array->disk_size = sb.capacity / sb.array.total_volumes;
level = 0;
disk_size = sb.capacity / sb.array.total_volumes;
break;
case NV_LEVEL_1:
array->level = 1;
array->disk_size = sb.capacity;
level = 1;
disk_size = sb.capacity;
break;
case NV_LEVEL_5:
array->level = 5;
array->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
array->disk_size = sb.capacity / (sb.array.total_volumes - 1);
level = 5;
layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
disk_size = sb.capacity / (sb.array.total_volumes - 1);
break;
default:
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", sb.array.raid_level);
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", sb.array.raid_level);
return NULL;
}
array->name = NULL;
array->number = 0;
array->total_devs = sb.array.total_volumes;
array->chunk_size = sb.array.stripe_block_size;
array->index = sb.unit_number;
array->uuid_len = sizeof (sb.array.signature);
array->uuid = grub_malloc (sizeof (sb.array.signature));
if (! array->uuid)
return grub_errno;
uuid = grub_malloc (sizeof (sb.array.signature));
if (! uuid)
return NULL;
grub_memcpy (array->uuid, (char *) &sb.array.signature,
grub_memcpy (uuid, (char *) &sb.array.signature,
sizeof (sb.array.signature));
id->uuidlen = 0;
id->id = sb.unit_number;
*start_sector = 0;
return 0;
return grub_diskfilter_make_raid (sizeof (sb.array.signature),
uuid, sb.array.total_volumes,
NULL, disk_size,
sb.array.stripe_block_size, layout,
level);
}
static struct grub_raid grub_dmraid_nv_dev =
static struct grub_diskfilter grub_dmraid_nv_dev =
{
.name = "dmraid_nv",
.detect = grub_dmraid_nv_detect,
@ -162,10 +183,10 @@ static struct grub_raid grub_dmraid_nv_dev =
GRUB_MOD_INIT(dm_nv)
{
grub_raid_register (&grub_dmraid_nv_dev);
grub_diskfilter_register (&grub_dmraid_nv_dev);
}
GRUB_MOD_FINI(dm_nv)
{
grub_raid_unregister (&grub_dmraid_nv_dev);
grub_diskfilter_unregister (&grub_dmraid_nv_dev);
}

View file

@ -664,38 +664,52 @@ grub_efidisk_get_device_handle (grub_disk_t disk)
return 0;
}
#define NEEDED_BUFLEN sizeof ("XdXXXXXXXXXX")
static inline int
get_diskname_from_path_real (const grub_efi_device_path_t *path,
struct grub_efidisk_data *head,
char *buf)
{
int count = 0;
struct grub_efidisk_data *d;
for (d = head, count = 0; d; d = d->next, count++)
if (grub_efi_compare_device_paths (d->device_path, path) == 0)
{
grub_snprintf (buf, NEEDED_BUFLEN - 1, "d%d", count);
return 1;
}
return 0;
}
static inline int
get_diskname_from_path (const grub_efi_device_path_t *path,
char *buf)
{
if (get_diskname_from_path_real (path, hd_devices, buf + 1))
{
buf[0] = 'h';
return 1;
}
if (get_diskname_from_path_real (path, fd_devices, buf + 1))
{
buf[0] = 'f';
return 1;
}
if (get_diskname_from_path_real (path, cd_devices, buf + 1))
{
buf[0] = 'c';
return 1;
}
return 0;
}
char *
grub_efidisk_get_device_name (grub_efi_handle_t *handle)
{
grub_efi_device_path_t *dp, *ldp, *sdp;
/* This is a hard disk partition. */
grub_disk_t parent = 0;
auto int find_parent_disk (const char *name);
/* Find the disk which is the parent of a given hard disk partition. */
int find_parent_disk (const char *name)
{
grub_disk_t disk;
disk = grub_disk_open (name);
if (! disk)
return 1;
if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
{
struct grub_efidisk_data *d;
d = disk->data;
if (grub_efi_compare_device_paths (d->device_path, sdp) == 0)
{
parent = disk;
return 1;
}
}
grub_disk_close (disk);
return 0;
}
grub_efi_device_path_t *dp, *ldp;
char device_name[NEEDED_BUFLEN];
dp = grub_efi_get_device_path (handle);
if (! dp)
@ -710,9 +724,11 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
{
char *partition_name = NULL;
char *device_name;
char *dev_name;
grub_efi_device_path_t *dup_dp, *dup_ldp;
grub_efi_hard_drive_device_path_t hd;
grub_disk_t parent = 0;
auto int find_partition (grub_disk_t disk, const grub_partition_t part);
/* Find the identical partition. */
@ -741,11 +757,9 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
dup_ldp->length[0] = sizeof (*dup_ldp);
dup_ldp->length[1] = 0;
sdp = dup_dp;
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
if (!parent)
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
if (!get_diskname_from_path (dup_dp, device_name))
return 0;
parent = grub_disk_open (device_name);
grub_free (dup_dp);
if (! parent)
@ -756,7 +770,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
if (hd.partition_start == 0
&& hd.partition_size == grub_disk_get_size (parent))
{
device_name = grub_strdup (parent->name);
dev_name = grub_strdup (parent->name);
}
else
{
@ -768,29 +782,18 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
return 0;
}
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
grub_free (partition_name);
}
grub_disk_close (parent);
return device_name;
return dev_name;
}
else
{
/* This should be an entire disk. */
char *device_name = 0;
sdp = dp;
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
if (!parent)
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
if (!parent)
return NULL;
device_name = grub_strdup (parent->name);
grub_disk_close (parent);
return device_name;
if (!get_diskname_from_path (dp, device_name))
return 0;
return grub_strdup (device_name);
}
return 0;
}

View file

@ -58,6 +58,38 @@
GRUB_MOD_LICENSE ("GPLv3+");
/* Dirty trick to solve circular dependency. */
#ifdef GRUB_UTIL
#include <grub/util/misc.h>
#undef GRUB_MD_SHA256
#undef GRUB_MD_SHA512
static const gcry_md_spec_t *
grub_md_sha256_real (void)
{
const gcry_md_spec_t *ret;
ret = grub_crypto_lookup_md_by_name ("sha256");
if (!ret)
grub_util_error ("Coulnd't load sha256");
return ret;
}
static const gcry_md_spec_t *
grub_md_sha512_real (void)
{
const gcry_md_spec_t *ret;
ret = grub_crypto_lookup_md_by_name ("sha512");
if (!ret)
grub_util_error ("Coulnd't load sha512");
return ret;
}
#define GRUB_MD_SHA256 grub_md_sha256_real()
#define GRUB_MD_SHA512 grub_md_sha512_real()
#endif
struct grub_geli_key
{
grub_uint8_t iv_key[64];
@ -194,7 +226,7 @@ grub_util_get_geli_uuid (const char *dev)
uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
grub_util_error ("couldn't read ELI metadata");
grub_util_error (_("couldn't read ELI metadata"));
COMPILE_TIME_ASSERT (sizeof (header) <= 512);
header = (void *) &hdr;
@ -203,7 +235,7 @@ grub_util_get_geli_uuid (const char *dev)
if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
|| grub_le_to_cpu32 (header->version) > 5
|| grub_le_to_cpu32 (header->version) < 1)
grub_util_error ("wrong ELI magic or version");
grub_util_error (_("wrong ELI magic or version"));
err = make_uuid ((void *) &hdr, uuid);
if (err)
@ -386,15 +418,15 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
keysize = grub_le_to_cpu16 (header.keylen) / 8;
grub_memset (zero, 0, sizeof (zero));
grub_printf ("Attempting to decrypt master key...\n");
grub_puts_ (N_("Attempting to decrypt master key..."));
/* Get the passphrase from the user. */
tmp = NULL;
if (source->partition)
tmp = grub_partition_get_name (source->partition);
grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name,
source->partition ? "," : "", tmp ? : "",
dev->uuid);
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
source->partition ? "," : "", tmp ? : "",
dev->uuid);
grub_free (tmp);
if (!grub_password_get (passphrase, MAX_PASSPHRASE))
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
@ -481,7 +513,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0)
continue;
grub_printf ("Slot %d opened\n", i);
grub_printf_ (N_("Slot %d opened\n"), i);
/* Set the master key. */
if (!dev->rekey)

View file

@ -27,6 +27,7 @@
#include <grub/misc.h>
#include <grub/err.h>
#include <grub/term.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -621,11 +622,12 @@ grub_disk_biosdisk_fini (void)
GRUB_MOD_INIT(biosdisk)
{
struct grub_biosdisk_cdrp *cdrp
= (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
= (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
grub_uint8_t boot_drive;
if (grub_disk_firmware_is_tainted)
{
grub_printf ("Firmware is marked as tainted, refusing to initialize.\n");
grub_puts_ (N_("Firmware is marked as tainted, refusing to initialize."));
return;
}
grub_disk_firmware_fini = grub_disk_biosdisk_fini;
@ -633,15 +635,16 @@ GRUB_MOD_INIT(biosdisk)
grub_memset (cdrp, 0, sizeof (*cdrp));
cdrp->size = sizeof (*cdrp);
cdrp->media_type = 0xFF;
if ((! grub_biosdisk_get_cdinfo_int13_extensions (grub_boot_drive, cdrp)) &&
((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
boot_drive = (grub_boot_device >> 24);
if ((! grub_biosdisk_get_cdinfo_int13_extensions (boot_drive, cdrp))
&& ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
cd_drive = cdrp->drive_no;
/* Since diskboot.S rejects devices over 0x90 it must be a CD booted with
cdboot.S
*/
if (grub_boot_drive >= 0x90)
cd_drive = grub_boot_drive;
if (boot_drive >= 0x90)
cd_drive = boot_drive;
grub_disk_dev_register (&grub_biosdisk_dev);
}

View file

@ -198,8 +198,14 @@ grub_ofdisk_iterate (int (*hook) (const char *name),
if (grub_strncmp (ent->shortest, "cdrom", 5) == 0)
continue;
if (hook (ent->shortest))
return 1;
{
char buffer[sizeof ("ieee1275/") + grub_strlen (ent->shortest)];
char *ptr;
ptr = grub_stpcpy (buffer, "ieee1275/");
grub_strcpy (ptr, ent->shortest);
if (hook (buffer))
return 1;
}
}
}
return 0;
@ -241,7 +247,10 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
char prop[64];
grub_ssize_t actual;
devpath = compute_dev_path (name);
if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"not IEEE1275 device");
devpath = compute_dev_path (name + sizeof ("ieee1275/") - 1);
if (! devpath)
return grub_errno;
@ -302,10 +311,9 @@ grub_ofdisk_close (grub_disk_t disk)
}
static grub_err_t
grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector)
{
grub_ssize_t status, actual;
grub_ssize_t status;
unsigned long long pos;
if (disk->data != last_devpath)
@ -334,15 +342,28 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
last_devpath = disk->data;
}
pos = sector * 512UL;
pos = sector << GRUB_DISK_SECTOR_BITS;
grub_ieee1275_seek (last_ihandle, pos, &status);
if (status < 0)
return grub_error (GRUB_ERR_READ_ERROR,
"seek error, can't seek block %llu",
(long long) sector);
grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual);
if (actual != (grub_ssize_t) (size * 512UL))
return 0;
}
static grub_err_t
grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_err_t err;
grub_ssize_t actual;
err = grub_ofdisk_prepare (disk, sector);
if (err)
return err;
grub_ieee1275_read (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS,
&actual);
if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS))
return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu",
(long long) sector);
@ -350,12 +371,21 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
}
static grub_err_t
grub_ofdisk_write (grub_disk_t disk __attribute ((unused)),
grub_disk_addr_t sector __attribute ((unused)),
grub_size_t size __attribute ((unused)),
const char *buf __attribute ((unused)))
grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, const char *buf)
{
return GRUB_ERR_NOT_IMPLEMENTED_YET;
grub_err_t err;
grub_ssize_t actual;
err = grub_ofdisk_prepare (disk, sector);
if (err)
return err;
grub_ieee1275_write (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS,
&actual);
if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS))
return grub_error (GRUB_ERR_WRITE_ERROR, "write error on block: %llu",
(long long) sector);
return 0;
}
static struct grub_disk_dev grub_ofdisk_dev =

997
grub-core/disk/ldm.c Normal file
View file

@ -0,0 +1,997 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2009,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/dl.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/diskfilter.h>
#include <grub/gpt_partition.h>
#ifdef GRUB_UTIL
#include <grub/emu/misc.h>
#include <grub/emu/hostdisk.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
#define LDM_GUID_STRLEN 64
#define LDM_NAME_STRLEN 32
typedef grub_uint8_t *grub_ldm_id_t;
enum { STRIPE = 1, SPANNED = 2, RAID5 = 3 };
#define LDM_LABEL_SECTOR 6
struct grub_ldm_vblk {
char magic[4];
grub_uint8_t unused1[12];
grub_uint16_t update_status;
grub_uint8_t flags;
grub_uint8_t type;
grub_uint32_t unused2;
grub_uint8_t dynamic[104];
} __attribute__ ((packed));
#define LDM_VBLK_MAGIC "VBLK"
enum
{
STATUS_CONSISTENT = 0,
STATUS_STILL_ACTIVE = 1,
STATUS_NOT_ACTIVE_YET = 2
};
enum
{
ENTRY_COMPONENT = 0x32,
ENTRY_PARTITION = 0x33,
ENTRY_DISK = 0x34,
ENTRY_VOLUME = 0x51,
};
struct grub_ldm_label
{
char magic[8];
grub_uint32_t unused1;
grub_uint16_t ver_major;
grub_uint16_t ver_minor;
grub_uint8_t unused2[32];
char disk_guid[LDM_GUID_STRLEN];
char host_guid[LDM_GUID_STRLEN];
char group_guid[LDM_GUID_STRLEN];
char group_name[LDM_NAME_STRLEN];
grub_uint8_t unused3[11];
grub_uint64_t pv_start;
grub_uint64_t pv_size;
grub_uint64_t config_start;
grub_uint64_t config_size;
} __attribute__ ((packed));
#define LDM_MAGIC "PRIVHEAD"
static inline grub_uint64_t
read_int (grub_uint8_t *in, grub_size_t s)
{
grub_uint8_t *ptr2;
grub_uint64_t ret;
ret = 0;
for (ptr2 = in; ptr2 < in + s; ptr2++)
{
ret <<= 8;
ret |= *ptr2;
}
return ret;
}
static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM;
static grub_disk_addr_t
gpt_ldm_sector (grub_disk_t dsk)
{
grub_disk_addr_t sector = 0;
grub_err_t err;
auto int hook (grub_disk_t disk, const grub_partition_t p);
int hook (grub_disk_t disk, const grub_partition_t p)
{
struct grub_gpt_partentry gptdata;
grub_partition_t p2;
p2 = disk->partition;
disk->partition = p->parent;
if (grub_disk_read (disk, p->offset, p->index,
sizeof (gptdata), &gptdata))
{
disk->partition = p2;
return 0;
}
disk->partition = p2;
if (! grub_memcmp (&gptdata.type, &ldm_type, 16))
{
sector = p->start + p->len - 1;
return 1;
}
return 0;
}
err = grub_gpt_partition_map_iterate (dsk, hook);
if (err)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
return sector;
}
static struct grub_diskfilter_vg *
make_vg (grub_disk_t disk,
const struct grub_ldm_label *label)
{
grub_disk_addr_t startsec, endsec, cursec;
struct grub_diskfilter_vg *vg;
grub_err_t err;
/* First time we see this volume group. We've to create the
whole volume group structure. */
vg = grub_malloc (sizeof (*vg));
if (! vg)
return NULL;
vg->extent_size = 1;
vg->name = grub_malloc (LDM_NAME_STRLEN + 1);
vg->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
if (! vg->uuid || !vg->name)
{
grub_free (vg->uuid);
grub_free (vg->name);
return NULL;
}
grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN);
grub_memcpy (vg->name, label->group_name, LDM_NAME_STRLEN);
vg->name[LDM_NAME_STRLEN] = 0;
vg->uuid[LDM_GUID_STRLEN] = 0;
vg->uuid_len = grub_strlen (vg->uuid);
vg->lvs = NULL;
vg->pvs = NULL;
startsec = grub_be_to_cpu64 (label->config_start);
endsec = startsec + grub_be_to_cpu64 (label->config_size);
/* First find disks. */
for (cursec = startsec + 0x12; cursec < endsec; cursec++)
{
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_ldm_vblk)];
unsigned i;
err = grub_disk_read (disk, cursec, 0,
sizeof(vblk), &vblk);
if (err)
goto fail2;
for (i = 0; i < ARRAY_SIZE (vblk); i++)
{
struct grub_diskfilter_pv *pv;
grub_uint8_t *ptr;
if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
sizeof (vblk[i].magic)) != 0)
continue;
if (grub_be_to_cpu16 (vblk[i].update_status)
!= STATUS_CONSISTENT
&& grub_be_to_cpu16 (vblk[i].update_status)
!= STATUS_STILL_ACTIVE)
continue;
if (vblk[i].type != ENTRY_DISK)
continue;
pv = grub_zalloc (sizeof (*pv));
if (!pv)
goto fail2;
pv->disk = 0;
ptr = vblk[i].dynamic;
if (ptr + *ptr + 1 >= vblk[i].dynamic
+ sizeof (vblk[i].dynamic))
{
grub_free (pv);
goto fail2;
}
pv->internal_id = grub_malloc (ptr[0] + 2);
if (!pv->internal_id)
{
grub_free (pv);
goto fail2;
}
grub_memcpy (pv->internal_id, ptr, (grub_size_t) ptr[0] + 1);
pv->internal_id[(grub_size_t) ptr[0] + 1] = 0;
ptr += *ptr + 1;
if (ptr + *ptr + 1 >= vblk[i].dynamic
+ sizeof (vblk[i].dynamic))
{
grub_free (pv);
goto fail2;
}
/* ptr = name. */
ptr += *ptr + 1;
if (ptr + *ptr + 1
>= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (pv);
goto fail2;
}
pv->id.uuidlen = *ptr;
pv->id.uuid = grub_malloc (pv->id.uuidlen + 1);
grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen);
pv->id.uuid[pv->id.uuidlen] = 0;
pv->next = vg->pvs;
vg->pvs = pv;
}
}
/* Then find LVs. */
for (cursec = startsec + 0x12; cursec < endsec; cursec++)
{
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_ldm_vblk)];
unsigned i;
err = grub_disk_read (disk, cursec, 0,
sizeof(vblk), &vblk);
if (err)
goto fail2;
for (i = 0; i < ARRAY_SIZE (vblk); i++)
{
struct grub_diskfilter_lv *lv;
grub_uint8_t *ptr;
if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
sizeof (vblk[i].magic)) != 0)
continue;
if (grub_be_to_cpu16 (vblk[i].update_status)
!= STATUS_CONSISTENT
&& grub_be_to_cpu16 (vblk[i].update_status)
!= STATUS_STILL_ACTIVE)
continue;
if (vblk[i].type != ENTRY_VOLUME)
continue;
lv = grub_zalloc (sizeof (*lv));
if (!lv)
goto fail2;
lv->vg = vg;
lv->segment_count = 1;
lv->segment_alloc = 1;
lv->visible = 1;
lv->segments = grub_zalloc (sizeof (*lv->segments));
if (!lv->segments)
goto fail2;
lv->segments->start_extent = 0;
lv->segments->type = GRUB_DISKFILTER_MIRROR;
lv->segments->node_count = 0;
lv->segments->node_alloc = 8;
lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes)
* lv->segments->node_alloc);
if (!lv->segments->nodes)
goto fail2;
ptr = vblk[i].dynamic;
if (ptr + *ptr + 1 >= vblk[i].dynamic
+ sizeof (vblk[i].dynamic))
{
grub_free (lv);
goto fail2;
}
lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
if (!lv->internal_id)
{
grub_free (lv);
goto fail2;
}
grub_memcpy (lv->internal_id, ptr, ptr[0] + 1);
lv->internal_id[ptr[0] + 1] = 0;
ptr += *ptr + 1;
if (ptr + *ptr + 1 >= vblk[i].dynamic
+ sizeof (vblk[i].dynamic))
{
grub_free (lv);
goto fail2;
}
lv->name = grub_malloc (*ptr + 1);
if (!lv->name)
{
grub_free (lv->internal_id);
grub_free (lv);
goto fail2;
}
grub_memcpy (lv->name, ptr + 1, *ptr);
lv->name[*ptr] = 0;
lv->fullname = grub_xasprintf ("ldm/%s/%s",
vg->uuid, lv->name);
if (!lv->fullname)
{
grub_free (lv->internal_id);
grub_free (lv->name);
grub_free (lv);
goto fail2;
}
ptr += *ptr + 1;
if (ptr + *ptr + 1
>= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (lv->internal_id);
grub_free (lv->name);
grub_free (lv);
goto fail2;
}
/* ptr = volume type. */
ptr += *ptr + 1;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (lv->internal_id);
grub_free (lv->name);
grub_free (lv);
goto fail2;
}
/* ptr = flags. */
ptr += *ptr + 1;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (lv->internal_id);
grub_free (lv->name);
grub_free (lv);
goto fail2;
}
/* Skip state, type, unknown, volume number, zeros, flags. */
ptr += 14 + 1 + 1 + 1 + 3 + 1;
/* ptr = number of children. */
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (lv->internal_id);
grub_free (lv->name);
grub_free (lv);
goto fail2;
}
ptr += *ptr + 1;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (lv->internal_id);
grub_free (lv->name);
grub_free (lv);
goto fail2;
}
/* Skip 2 more fields. */
ptr += 8 + 8;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|| ptr + *ptr + 1>= vblk[i].dynamic
+ sizeof (vblk[i].dynamic))
{
grub_free (lv->internal_id);
grub_free (lv->name);
grub_free (lv);
goto fail2;
}
lv->size = read_int (ptr + 1, *ptr);
lv->segments->extent_count = lv->size;
lv->next = vg->lvs;
vg->lvs = lv;
}
}
/* Now the components. */
for (cursec = startsec + 0x12; cursec < endsec; cursec++)
{
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_ldm_vblk)];
unsigned i;
err = grub_disk_read (disk, cursec, 0,
sizeof(vblk), &vblk);
if (err)
goto fail2;
for (i = 0; i < ARRAY_SIZE (vblk); i++)
{
struct grub_diskfilter_lv *comp;
struct grub_diskfilter_lv *lv;
grub_uint8_t type;
grub_uint8_t *ptr;
if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
sizeof (vblk[i].magic)) != 0)
continue;
if (grub_be_to_cpu16 (vblk[i].update_status)
!= STATUS_CONSISTENT
&& grub_be_to_cpu16 (vblk[i].update_status)
!= STATUS_STILL_ACTIVE)
continue;
if (vblk[i].type != ENTRY_COMPONENT)
continue;
comp = grub_zalloc (sizeof (*comp));
if (!comp)
goto fail2;
comp->visible = 0;
comp->name = 0;
comp->fullname = 0;
ptr = vblk[i].dynamic;
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
goto fail2;
}
comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
if (!comp->internal_id)
{
grub_free (comp);
goto fail2;
}
grub_memcpy (comp->internal_id, ptr, ptr[0] + 1);
comp->internal_id[ptr[0] + 1] = 0;
ptr += *ptr + 1;
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (comp->internal_id);
grub_free (comp);
goto fail2;
}
/* ptr = name. */
ptr += *ptr + 1;
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (comp->internal_id);
grub_free (comp);
goto fail2;
}
/* ptr = state. */
ptr += *ptr + 1;
type = *ptr++;
/* skip zeros. */
ptr += 4;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (comp->internal_id);
grub_free (comp);
goto fail2;
}
/* ptr = number of children. */
ptr += *ptr + 1;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
grub_free (comp->internal_id);
grub_free (comp);
goto fail2;
}
ptr += 8 + 8;
if (ptr + *ptr + 1 >= vblk[i].dynamic
+ sizeof (vblk[i].dynamic))
{
grub_free (comp->internal_id);
grub_free (comp);
goto fail2;
}
for (lv = vg->lvs; lv; lv = lv->next)
{
if (lv->internal_id[0] == ptr[0]
&& grub_memcmp (lv->internal_id + 1, ptr + 1, ptr[0]) == 0)
break;
}
if (!lv)
{
grub_free (comp->internal_id);
grub_free (comp);
continue;
}
comp->size = lv->size;
if (type == SPANNED)
{
comp->segment_alloc = 8;
comp->segment_count = 0;
comp->segments = grub_malloc (sizeof (*comp->segments)
* comp->segment_alloc);
if (!comp->segments)
goto fail2;
}
else
{
comp->segment_alloc = 1;
comp->segment_count = 1;
comp->segments = grub_malloc (sizeof (*comp->segments));
if (!comp->segments)
goto fail2;
comp->segments->start_extent = 0;
comp->segments->extent_count = lv->size;
comp->segments->layout = 0;
if (type == STRIPE)
comp->segments->type = GRUB_DISKFILTER_STRIPED;
else if (type == RAID5)
{
comp->segments->type = GRUB_DISKFILTER_RAID5;
comp->segments->layout = GRUB_RAID_LAYOUT_SYMMETRIC_MASK;
}
else
goto fail2;
ptr += *ptr + 1;
ptr++;
if (!(vblk[i].flags & 0x10))
goto fail2;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|| ptr + *ptr + 1 >= vblk[i].dynamic
+ sizeof (vblk[i].dynamic))
{
grub_free (comp->internal_id);
grub_free (comp);
goto fail2;
}
comp->segments->stripe_size = read_int (ptr + 1, *ptr);
ptr += *ptr + 1;
if (ptr + *ptr + 1 >= vblk[i].dynamic
+ sizeof (vblk[i].dynamic))
{
grub_free (comp->internal_id);
grub_free (comp);
goto fail2;
}
comp->segments->node_count = read_int (ptr + 1, *ptr);
comp->segments->node_alloc = comp->segments->node_count;
comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes)
* comp->segments->node_alloc);
if (!lv->segments->nodes)
goto fail2;
}
if (lv->segments->node_alloc == lv->segments->node_count)
{
void *t;
lv->segments->node_alloc *= 2;
t = grub_realloc (lv->segments->nodes,
sizeof (*lv->segments->nodes)
* lv->segments->node_alloc);
if (!t)
goto fail2;
lv->segments->nodes = t;
}
lv->segments->nodes[lv->segments->node_count].pv = 0;
lv->segments->nodes[lv->segments->node_count].start = 0;
lv->segments->nodes[lv->segments->node_count++].lv = comp;
comp->next = vg->lvs;
vg->lvs = comp;
}
}
/* Partitions. */
for (cursec = startsec + 0x12; cursec < endsec; cursec++)
{
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_ldm_vblk)];
unsigned i;
err = grub_disk_read (disk, cursec, 0,
sizeof(vblk), &vblk);
if (err)
goto fail2;
for (i = 0; i < ARRAY_SIZE (vblk); i++)
{
struct grub_diskfilter_lv *comp;
struct grub_diskfilter_node part;
grub_disk_addr_t start, size;
grub_uint8_t *ptr;
if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
sizeof (vblk[i].magic)) != 0)
continue;
if (grub_be_to_cpu16 (vblk[i].update_status)
!= STATUS_CONSISTENT
&& grub_be_to_cpu16 (vblk[i].update_status)
!= STATUS_STILL_ACTIVE)
continue;
if (vblk[i].type != ENTRY_PARTITION)
continue;
part.lv = 0;
part.pv = 0;
ptr = vblk[i].dynamic;
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
goto fail2;
}
/* ID */
ptr += *ptr + 1;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
goto fail2;
}
/* ptr = name. */
ptr += *ptr + 1;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
goto fail2;
}
/* skip zeros and logcommit id. */
ptr += 4 + 8;
if (ptr + 16 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
goto fail2;
}
part.start = read_int (ptr, 8);
start = read_int (ptr + 8, 8);
ptr += 16;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|| ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
goto fail2;
}
size = read_int (ptr + 1, *ptr);
ptr += *ptr + 1;
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|| ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
goto fail2;
}
for (comp = vg->lvs; comp; comp = comp->next)
if (comp->internal_id[0] == ptr[0]
&& grub_memcmp (ptr + 1, comp->internal_id + 1,
comp->internal_id[0]) == 0)
goto out;
continue;
out:
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|| ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
{
goto fail2;
}
ptr += *ptr + 1;
struct grub_diskfilter_pv *pv;
for (pv = vg->pvs; pv; pv = pv->next)
if (pv->internal_id[0] == ptr[0]
&& grub_memcmp (pv->internal_id + 1, ptr + 1, ptr[0]) == 0)
part.pv = pv;
if (comp->segment_alloc == 1)
{
unsigned index;
ptr += *ptr + 1;
if (ptr + *ptr + 1 >= vblk[i].dynamic
+ sizeof (vblk[i].dynamic))
{
goto fail2;
}
index = read_int (ptr + 1, *ptr);
if (index < comp->segments->node_count)
comp->segments->nodes[index] = part;
}
else
{
if (comp->segment_alloc == comp->segment_count)
{
void *t;
comp->segment_alloc *= 2;
t = grub_realloc (comp->segments,
comp->segment_alloc
* sizeof (*comp->segments));
if (!t)
goto fail2;
comp->segments = t;
}
comp->segments[comp->segment_count].start_extent = start;
comp->segments[comp->segment_count].extent_count = size;
comp->segments[comp->segment_count].type = GRUB_DISKFILTER_STRIPED;
comp->segments[comp->segment_count].node_count = 1;
comp->segments[comp->segment_count].node_alloc = 1;
comp->segments[comp->segment_count].nodes
= grub_malloc (sizeof (*comp->segments[comp->segment_count].nodes));
if (!comp->segments[comp->segment_count].nodes)
goto fail2;
comp->segments[comp->segment_count].nodes[0] = part;
comp->segment_count++;
}
}
}
if (grub_diskfilter_vg_register (vg))
goto fail2;
return vg;
fail2:
{
struct grub_diskfilter_lv *lv, *next_lv;
struct grub_diskfilter_pv *pv, *next_pv;
for (lv = vg->lvs; lv; lv = next_lv)
{
unsigned i;
for (i = 0; i < lv->segment_count; i++)
grub_free (lv->segments[i].nodes);
next_lv = lv->next;
grub_free (lv->segments);
grub_free (lv->internal_id);
grub_free (lv->name);
grub_free (lv->fullname);
grub_free (lv);
}
for (pv = vg->pvs; pv; pv = next_pv)
{
next_pv = pv->next;
grub_free (pv->id.uuid);
grub_free (pv);
}
}
grub_free (vg->uuid);
grub_free (vg);
return NULL;
}
static struct grub_diskfilter_vg *
grub_ldm_detect (grub_disk_t disk,
struct grub_diskfilter_pv_id *id,
grub_disk_addr_t *start_sector)
{
grub_err_t err;
struct grub_ldm_label label;
struct grub_diskfilter_vg *vg;
#ifdef GRUB_UTIL
grub_util_info ("scanning %s for LDM", disk->name);
#endif
{
int i;
for (i = 0; i < 3; i++)
{
grub_disk_addr_t sector;
switch (i)
{
case 0:
sector = LDM_LABEL_SECTOR;
break;
case 1:
/* LDM is never inside a partition. */
if (disk->partition)
continue;
sector = grub_disk_get_size (disk);
if (sector == GRUB_DISK_SIZE_UNKNOWN)
continue;
sector--;
break;
/* FIXME: try the third copy. */
case 2:
sector = gpt_ldm_sector (disk);
if (!sector)
continue;
break;
}
err = grub_disk_read (disk, sector, 0,
sizeof(label), &label);
if (err)
return NULL;
if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0
&& grub_be_to_cpu16 (label.ver_major) == 0x02
&& grub_be_to_cpu16 (label.ver_minor) >= 0x0b
&& grub_be_to_cpu16 (label.ver_minor) <= 0x0c)
break;
}
/* Return if we didn't find a label. */
if (i == 3)
{
#ifdef GRUB_UTIL
grub_util_info ("no LDM signature found");
#endif
return NULL;
}
}
id->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
if (!id->uuid)
return NULL;
grub_memcpy (id->uuid, label.disk_guid, LDM_GUID_STRLEN);
id->uuid[LDM_GUID_STRLEN] = 0;
id->uuidlen = grub_strlen ((char *) id->uuid);
*start_sector = grub_be_to_cpu64 (label.pv_start);
{
grub_size_t s;
for (s = 0; s < LDM_GUID_STRLEN && label.group_guid[s]; s++);
vg = grub_diskfilter_get_vg_by_uuid (s, label.group_guid);
if (! vg)
vg = make_vg (disk, &label);
}
if (!vg)
{
grub_free (id->uuid);
return NULL;
}
return vg;
}
#ifdef GRUB_UTIL
char *
grub_util_get_ldm (grub_disk_t disk, grub_disk_addr_t start)
{
struct grub_diskfilter_pv *pv = NULL;
struct grub_diskfilter_vg *vg = NULL;
struct grub_diskfilter_lv *res, *lv;
int i;
pv = grub_diskfilter_get_pv_from_disk (disk, &vg);
if (!pv)
return NULL;
for (lv = vg->lvs; lv; lv = lv->next)
if (lv->segment_count == 1 && lv->segments->node_count == 1
&& lv->segments->type == GRUB_DISKFILTER_STRIPED
&& lv->segments->nodes->pv == pv
&& lv->segments->nodes->start + pv->start_sector == start)
{
res = lv;
break;
}
for (lv = vg->lvs; lv; lv = lv->next)
if (lv->segment_count == 1 && lv->segments->node_count == 1
&& lv->segments->type == GRUB_DISKFILTER_MIRROR
&& lv->segments->nodes->lv == lv)
{
res = lv;
break;
}
if (res->fullname)
return grub_strdup (lv->fullname);
return NULL;
}
int
grub_util_is_ldm (grub_disk_t disk)
{
int i;
for (i = 0; i < 3; i++)
{
grub_disk_addr_t sector;
grub_err_t err;
struct grub_ldm_label label;
switch (i)
{
case 0:
sector = LDM_LABEL_SECTOR;
break;
case 1:
/* LDM is never inside a partition. */
if (disk->partition)
continue;
sector = grub_disk_get_size (disk);
if (sector == GRUB_DISK_SIZE_UNKNOWN)
continue;
sector--;
break;
/* FIXME: try the third copy. */
case 2:
sector = gpt_ldm_sector (disk);
if (!sector)
continue;
break;
}
err = grub_disk_read (disk, sector, 0, sizeof(label), &label);
if (err)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
/* This check is more relaxed on purpose. */
if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0)
return 1;
}
return 0;
}
grub_err_t
grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors,
grub_embed_type_t embed_type,
grub_disk_addr_t **sectors)
{
struct grub_diskfilter_pv *pv = NULL;
struct grub_diskfilter_vg *vg;
struct grub_diskfilter_lv *lv;
unsigned i;
if (embed_type != GRUB_EMBED_PCBIOS)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"GPT curently supports only PC-BIOS embedding");
if (disk->partition)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "disk isn't LDM");
pv = grub_diskfilter_get_pv_from_disk (disk, &vg);
if (!pv)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "disk isn't LDM");
for (lv = vg->lvs; lv; lv = lv->next)
{
struct grub_diskfilter_lv *comp;
struct grub_ldm_partition *part;
if (!lv->visible || !lv->fullname)
continue;
if (lv->segment_count != 1)
continue;
if (lv->segments->type != GRUB_DISKFILTER_MIRROR
|| lv->segments->node_count != 1
|| lv->segments->start_extent != 0
|| lv->segments->extent_count != lv->size)
continue;
comp = lv->segments->nodes->lv;
if (!comp)
continue;
if (comp->segment_count != 1 || comp->size != lv->size)
continue;
if (comp->segments->type != GRUB_DISKFILTER_STRIPED
|| comp->segments->node_count != 1
|| comp->segments->start_extent != 0
|| comp->segments->extent_count != lv->size)
continue;
/* How to implement proper check is to be discussed. */
#if 1
if (1)
continue;
#else
if (grub_strcmp (lv->name, "Volume5") != 0)
continue;
#endif
if (lv->size < *nsectors)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"Your LDM embed Partition is too small;"
" embedding won't be possible!");
*nsectors = lv->size;
*sectors = grub_malloc (*nsectors * sizeof (**sectors));
if (!*sectors)
return grub_errno;
for (i = 0; i < *nsectors; i++)
(*sectors)[i] = (lv->segments->nodes->start
+ comp->segments->nodes->start
+ comp->segments->nodes->pv->start_sector + i);
return GRUB_ERR_NONE;
}
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
"This LDM no Embedding Partition;"
" embedding won't be possible!");
}
#endif
static struct grub_diskfilter grub_ldm_dev = {
.name = "ldm",
.detect = grub_ldm_detect,
.next = 0
};
GRUB_MOD_INIT (ldm)
{
grub_diskfilter_register (&grub_ldm_dev);
}
GRUB_MOD_FINI (ldm)
{
grub_diskfilter_unregister (&grub_ldm_dev);
}

View file

@ -316,7 +316,7 @@ luks_recover_key (grub_disk_t source,
if (err)
return err;
grub_printf ("Attempting to decrypt master key...\n");
grub_puts_ (N_("Attempting to decrypt master key..."));
keysize = grub_be_to_cpu32 (header.keyBytes);
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
@ -332,7 +332,7 @@ luks_recover_key (grub_disk_t source,
tmp = NULL;
if (source->partition)
tmp = grub_partition_get_name (source->partition);
grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name,
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
source->partition ? "," : "", tmp ? : "",
dev->uuid);
grub_free (tmp);
@ -434,7 +434,7 @@ luks_recover_key (grub_disk_t source,
continue;
}
grub_printf ("Slot %d opened\n", i);
grub_printf_ (N_("Slot %d opened\n"), i);
/* Set the master key. */
gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize);

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,7 @@
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
#include <grub/diskfilter.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -103,8 +103,9 @@ struct grub_raid_super_1x
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
static grub_err_t
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
static struct grub_diskfilter_vg *
grub_mdraid_detect (grub_disk_t disk,
struct grub_diskfilter_pv_id *id,
grub_disk_addr_t *start_sector)
{
grub_disk_addr_t sector = 0;
@ -142,7 +143,7 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
&sb))
return grub_errno;
return NULL;
if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC
|| grub_le_to_cpu64 (sb.super_offset) != sector)
@ -154,9 +155,12 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_uint32_t level;
if (grub_le_to_cpu32 (sb.major_version) != 1)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID version: %d",
grub_le_to_cpu32 (sb.major_version));
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID version: %d",
grub_le_to_cpu32 (sb.major_version));
return NULL;
}
level = grub_le_to_cpu32 (sb.level);
@ -166,8 +170,11 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
if (level != 0 && level != 1 && level != 4 &&
level != 5 && level != 6 && level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID level: %d", sb.level);
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID level: %d", sb.level);
return NULL;
}
/* 1.x superblocks don't have a fixed size on disk. So we have to
read it again now that we now the max device count. */
@ -175,62 +182,68 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
+ 2 * grub_le_to_cpu32 (sb.max_dev);
real_sb = grub_malloc (sb_size);
if (! real_sb)
return grub_errno;
return NULL;
if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
{
grub_free (real_sb);
return grub_errno;
return NULL;
}
array->name = grub_strdup (real_sb->set_name);
if (! array->name)
{
grub_free (real_sb);
return grub_errno;
}
array->number = 0;
array->level = grub_le_to_cpu32 (real_sb->level);
array->layout = grub_le_to_cpu32 (real_sb->layout);
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
if (real_sb->size)
array->disk_size = grub_le_to_cpu64 (real_sb->size);
else
array->disk_size = grub_le_to_cpu64 (real_sb->data_size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
struct grub_diskfilter_vg *array;
char *uuid;
if (grub_le_to_cpu32 (real_sb->dev_number) >=
grub_le_to_cpu32 (real_sb->max_dev))
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"spares aren't implemented");
array->index = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
if (array->index >= array->total_devs)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"spares aren't implemented");
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
{
grub_free (real_sb);
return grub_errno;
grub_error (GRUB_ERR_OUT_OF_RANGE,
"spares aren't implemented");
return NULL;
}
grub_memcpy (array->uuid, real_sb->set_uuid, 16);
id->uuidlen = 0;
id->id = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
uuid = grub_malloc (16);
if (!uuid)
{
grub_free (real_sb);
return NULL;
}
grub_memcpy (uuid, real_sb->set_uuid, 16);
*start_sector = grub_le_to_cpu64 (real_sb->data_offset);
if (grub_le_to_cpu32 (real_sb->dev_number)
>= grub_le_to_cpu32 (real_sb->raid_disks))
{
grub_error (GRUB_ERR_OUT_OF_RANGE,
"spares aren't implemented");
return NULL;
}
array = grub_diskfilter_make_raid (16, uuid,
grub_le_to_cpu32 (real_sb->raid_disks),
real_sb->set_name,
(real_sb->size)
? grub_le_to_cpu64 (real_sb->size)
: grub_le_to_cpu64 (real_sb->data_size),
grub_le_to_cpu32 (real_sb->chunksize),
grub_le_to_cpu32 (real_sb->layout),
grub_le_to_cpu32 (real_sb->level));
grub_free (real_sb);
return 0;
return array;
}
}
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid");
grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid");
return NULL;
}
static struct grub_raid grub_mdraid_dev = {
static struct grub_diskfilter grub_mdraid_dev = {
.name = "mdraid1x",
.detect = grub_mdraid_detect,
.next = 0
@ -238,10 +251,10 @@ static struct grub_raid grub_mdraid_dev = {
GRUB_MOD_INIT (mdraid1x)
{
grub_raid_register (&grub_mdraid_dev);
grub_diskfilter_register (&grub_mdraid_dev);
}
GRUB_MOD_FINI (mdraid1x)
{
grub_raid_unregister (&grub_mdraid_dev);
grub_diskfilter_unregister (&grub_mdraid_dev);
}

View file

@ -22,7 +22,7 @@
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
#include <grub/diskfilter.h>
/* Linux RAID on disk structures and constants,
copied from include/linux/raid/md_p.h. */
@ -161,8 +161,9 @@ struct grub_raid_super_09
struct grub_raid_disk_09 this_disk;
} __attribute__ ((packed));
static grub_err_t
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
static struct grub_diskfilter_vg *
grub_mdraid_detect (grub_disk_t disk,
struct grub_diskfilter_pv_id *id,
grub_disk_addr_t *start_sector)
{
grub_disk_addr_t sector;
@ -174,22 +175,31 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
/* The sector where the mdraid 0.90 superblock is stored, if available. */
size = grub_disk_get_size (disk);
if (size == GRUB_DISK_SIZE_UNKNOWN)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
return NULL;
}
sector = NEW_SIZE_SECTORS (size);
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb))
return grub_errno;
return NULL;
/* Look whether there is a mdraid 0.90 superblock. */
if (grub_le_to_cpu32 (sb.md_magic) != SB_MAGIC)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
return NULL;
}
if (grub_le_to_cpu32 (sb.major_version) != 0
|| grub_le_to_cpu32 (sb.minor_version) != 90)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID version: %d.%d",
grub_le_to_cpu32 (sb.major_version),
grub_le_to_cpu32 (sb.minor_version));
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID version: %d.%d",
grub_le_to_cpu32 (sb.major_version),
grub_le_to_cpu32 (sb.minor_version));
return NULL;
}
/* FIXME: Check the checksum. */
@ -200,27 +210,23 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
if (level != 0 && level != 1 && level != 4 &&
level != 5 && level != 6 && level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", level);
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", level);
return NULL;
}
if (grub_le_to_cpu32 (sb.this_disk.number) == 0xffff
|| grub_le_to_cpu32 (sb.this_disk.number) == 0xfffe)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"spares aren't implemented");
{
grub_error (GRUB_ERR_OUT_OF_RANGE,
"spares aren't implemented");
return NULL;
}
array->name = NULL;
array->number = grub_le_to_cpu32 (sb.md_minor);
array->level = level;
array->layout = grub_le_to_cpu32 (sb.layout);
array->total_devs = grub_le_to_cpu32 (sb.raid_disks);
array->disk_size = (sb.size) ? grub_le_to_cpu32 (sb.size) * 2 : sector;
array->chunk_size = grub_le_to_cpu32 (sb.chunk_size) >> 9;
array->index = grub_le_to_cpu32 (sb.this_disk.number);
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
return grub_errno;
uuid = grub_malloc (16);
if (!uuid)
return NULL;
uuid = (grub_uint32_t *) array->uuid;
uuid[0] = grub_swap_bytes32 (sb.set_uuid0);
uuid[1] = grub_swap_bytes32 (sb.set_uuid1);
uuid[2] = grub_swap_bytes32 (sb.set_uuid2);
@ -228,10 +234,21 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
*start_sector = 0;
return 0;
id->uuidlen = 0;
id->id = grub_le_to_cpu32 (sb.this_disk.number);
char buf[32];
grub_snprintf (buf, sizeof (buf), "md%d", grub_le_to_cpu32 (sb.md_minor));
return grub_diskfilter_make_raid (16, (char *) uuid,
grub_le_to_cpu32 (sb.raid_disks), buf,
(sb.size) ? grub_le_to_cpu32 (sb.size) * 2
: sector,
grub_le_to_cpu32 (sb.chunk_size) >> 9,
grub_le_to_cpu32 (sb.layout),
level);
}
static struct grub_raid grub_mdraid_dev = {
static struct grub_diskfilter grub_mdraid_dev = {
.name = "mdraid09",
.detect = grub_mdraid_detect,
.next = 0
@ -239,10 +256,10 @@ static struct grub_raid grub_mdraid_dev = {
GRUB_MOD_INIT (mdraid09)
{
grub_raid_register (&grub_mdraid_dev);
grub_diskfilter_register (&grub_mdraid_dev);
}
GRUB_MOD_FINI (mdraid09)
{
grub_raid_unregister (&grub_mdraid_dev);
grub_diskfilter_unregister (&grub_mdraid_dev);
}

View file

@ -86,30 +86,24 @@ static struct grub_disk_dev grub_memdisk_dev =
GRUB_MOD_INIT(memdisk)
{
auto int hook (struct grub_module_header *);
int hook (struct grub_module_header *header)
{
if (header->type == OBJ_TYPE_MEMDISK)
{
char *memdisk_orig_addr;
memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header);
struct grub_module_header *header;
FOR_MODULES (header)
if (header->type == OBJ_TYPE_MEMDISK)
{
char *memdisk_orig_addr;
memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header);
grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
memdisk_size = header->size - sizeof (struct grub_module_header);
memdisk_addr = grub_malloc (memdisk_size);
memdisk_size = header->size - sizeof (struct grub_module_header);
memdisk_addr = grub_malloc (memdisk_size);
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
grub_disk_dev_register (&grub_memdisk_dev);
return 1;
}
return 0;
}
grub_module_iterate (hook);
grub_disk_dev_register (&grub_memdisk_dev);
break;
}
}
GRUB_MOD_FINI(memdisk)

View file

@ -116,12 +116,13 @@ grub_pata_wait (void)
static void
grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
{
grub_uint16_t *buf16 = (grub_uint16_t *) buf;
unsigned int i;
/* Read in the data, word by word. */
for (i = 0; i < size / 2; i++)
buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA));
grub_set_unaligned16 (buf + 2 * i,
grub_le_to_cpu16 (grub_inw(dev->ioaddress
+ GRUB_ATA_REG_DATA)));
if (size & 1)
buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress
+ GRUB_ATA_REG_DATA));
@ -130,12 +131,11 @@ grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
static void
grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size)
{
grub_uint16_t *buf16 = (grub_uint16_t *) buf;
unsigned int i;
/* Write the data, word by word. */
for (i = 0; i < size / 2; i++)
grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA);
grub_outw(grub_cpu_to_le16 (grub_get_unaligned16 (buf + 2 * i)), dev->ioaddress + GRUB_ATA_REG_DATA);
}
/* ATA pass through support, used by hdparm.mod. */
@ -484,6 +484,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata)
ata->data = devfnd;
ata->dma = 0;
ata->maxbuffer = 256 * 512;
ata->present = &devfnd->present;
return GRUB_ERR_NONE;

View file

@ -1,934 +0,0 @@
/* raid.c - module to read RAID arrays. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/dl.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
#ifdef GRUB_UTIL
#include <grub/util/misc.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
/* Linked list of RAID arrays. */
static struct grub_raid_array *array_list;
grub_raid5_recover_func_t grub_raid5_recover_func;
grub_raid6_recover_func_t grub_raid6_recover_func;
static grub_raid_t grub_raid_list;
static int inscnt = 0;
static struct grub_raid_array *
find_array (const char *name);
static char
grub_is_array_readable (struct grub_raid_array *array)
{
switch (array->level)
{
case 0:
if (array->nr_devs == array->total_devs)
return 1;
break;
case 1:
if (array->nr_devs >= 1)
return 1;
break;
case 4:
case 5:
case 6:
case 10:
{
unsigned int n;
if (array->level == 10)
{
n = array->layout & 0xFF;
if (n == 1)
n = (array->layout >> 8) & 0xFF;
n--;
}
else
n = array->level / 3;
if (array->nr_devs >= array->total_devs - n)
return 1;
break;
}
}
return 0;
}
static grub_err_t
insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_disk_addr_t start_sector, const char *scanner_name,
grub_raid_t raid __attribute__ ((unused)));
static int scan_depth = 0;
static void
scan_devices (const char *arname)
{
grub_raid_t raid;
auto int hook (const char *name);
int hook (const char *name)
{
grub_disk_t disk;
struct grub_raid_array array;
struct grub_raid_array *arr;
grub_disk_addr_t start_sector;
grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
raid->name, name);
#ifdef GRUB_UTIL
grub_util_info ("Scanning for %s RAID devices on disk %s",
raid->name, name);
#endif
disk = grub_disk_open (name);
if (!disk)
return 0;
for (arr = array_list; arr != NULL; arr = arr->next)
{
struct grub_raid_member *m;
for (m = arr->members; m < arr->members + arr->nr_devs; m++)
if (m->device && m->device->id == disk->id
&& m->device->dev->id == m->device->dev->id)
{
grub_disk_close (disk);
return 0;
}
}
if ((disk->total_sectors != GRUB_ULONG_MAX) &&
(! raid->detect (disk, &array, &start_sector)) &&
(! insert_array (disk, &array, start_sector, raid->name,
raid)))
return 0;
/* This error usually means it's not raid, no need to display
it. */
if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_disk_close (disk);
if (arname && find_array (arname))
return 1;
return 0;
}
if (scan_depth)
return;
scan_depth++;
for (raid = grub_raid_list; raid; raid = raid->next)
grub_device_iterate (&hook);
scan_depth--;
}
static int
grub_raid_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
struct grub_raid_array *array;
int islcnt = 0;
if (pull == GRUB_DISK_PULL_RESCAN)
{
islcnt = inscnt;
scan_devices (NULL);
}
if (pull != GRUB_DISK_PULL_NONE && pull != GRUB_DISK_PULL_RESCAN)
return 0;
for (array = array_list; array != NULL; array = array->next)
{
if (grub_is_array_readable (array) && array->became_readable_at >= islcnt)
if (hook (array->name))
return 1;
}
return 0;
}
#ifdef GRUB_UTIL
static grub_disk_memberlist_t
grub_raid_memberlist (grub_disk_t disk)
{
struct grub_raid_array *array = disk->data;
grub_disk_memberlist_t list = NULL, tmp;
unsigned int i;
for (i = 0; i < array->total_devs; i++)
if (array->members[i].device)
{
tmp = grub_malloc (sizeof (*tmp));
tmp->disk = array->members[i].device;
tmp->next = list;
list = tmp;
}
return list;
}
static const char *
grub_raid_getname (struct grub_disk *disk)
{
struct grub_raid_array *array = disk->data;
return array->driver->name;
}
#endif
static inline int
ascii2hex (char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return 0;
}
static struct grub_raid_array *
find_array (const char *name)
{
struct grub_raid_array *array;
if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0)
{
const char *uuidstr = name + sizeof ("mduuid/") - 1;
grub_size_t uuid_len = grub_strlen (uuidstr) / 2;
grub_uint8_t uuidbin[uuid_len];
unsigned i;
for (i = 0; i < uuid_len; i++)
uuidbin[i] = ascii2hex (uuidstr[2 * i + 1])
| (ascii2hex (uuidstr[2 * i]) << 4);
for (array = array_list; array != NULL; array = array->next)
{
if (uuid_len == (unsigned) array->uuid_len
&& grub_memcmp (uuidbin, array->uuid, uuid_len) == 0)
if (grub_is_array_readable (array))
return array;
}
}
else
for (array = array_list; array != NULL; array = array->next)
{
if (!grub_strcmp (array->name, name))
if (grub_is_array_readable (array))
return array;
}
return NULL;
}
static grub_err_t
grub_raid_open (const char *name, grub_disk_t disk)
{
struct grub_raid_array *array;
unsigned n;
if (grub_memcmp (name, "md", sizeof ("md") - 1) != 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
name);
array = find_array (name);
if (! array)
{
scan_devices (name);
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
array = find_array (name);
}
if (!array)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
name);
disk->id = array->number;
disk->data = array;
grub_dprintf ("raid", "%s: total_devs=%d, disk_size=%lld\n", name,
array->total_devs, (unsigned long long) array->disk_size);
switch (array->level)
{
case 1:
disk->total_sectors = array->disk_size;
break;
case 10:
n = array->layout & 0xFF;
if (n == 1)
n = (array->layout >> 8) & 0xFF;
disk->total_sectors = grub_divmod64 (array->total_devs *
array->disk_size,
n, 0);
break;
case 0:
case 4:
case 5:
case 6:
n = array->level / 3;
disk->total_sectors = (array->total_devs - n) * array->disk_size;
break;
}
grub_dprintf ("raid", "%s: level=%d, total_sectors=%lld\n", name,
array->level, (unsigned long long) disk->total_sectors);
return 0;
}
static void
grub_raid_close (grub_disk_t disk __attribute ((unused)))
{
return;
}
void
grub_raid_block_xor (char *buf1, const char *buf2, int size)
{
grub_size_t *p1;
const grub_size_t *p2;
p1 = (grub_size_t *) buf1;
p2 = (const grub_size_t *) buf2;
size /= GRUB_CPU_SIZEOF_VOID_P;
while (size)
{
*(p1++) ^= *(p2++);
size--;
}
}
static grub_err_t
grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
struct grub_raid_array *array = disk->data;
grub_err_t err = 0;
switch (array->level)
{
case 0:
case 1:
case 10:
{
grub_disk_addr_t read_sector, far_ofs;
grub_uint64_t disknr, b, near, far, ofs;
read_sector = grub_divmod64 (sector, array->chunk_size, &b);
far = ofs = near = 1;
far_ofs = 0;
if (array->level == 1)
near = array->total_devs;
else if (array->level == 10)
{
near = array->layout & 0xFF;
far = (array->layout >> 8) & 0xFF;
if (array->layout >> 16)
{
ofs = far;
far_ofs = 1;
}
else
far_ofs = grub_divmod64 (array->disk_size,
far * array->chunk_size, 0);
far_ofs *= array->chunk_size;
}
read_sector = grub_divmod64 (read_sector * near, array->total_devs,
&disknr);
ofs *= array->chunk_size;
read_sector *= ofs;
while (1)
{
grub_size_t read_size;
unsigned int i, j;
read_size = array->chunk_size - b;
if (read_size > size)
read_size = size;
for (i = 0; i < near; i++)
{
unsigned int k;
k = disknr;
for (j = 0; j < far; j++)
{
if (array->members[k].device)
{
if (grub_errno == GRUB_ERR_READ_ERROR)
grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->members[k].device,
array->members[k].start_sector +
read_sector + j * far_ofs + b,
0,
read_size << GRUB_DISK_SECTOR_BITS,
buf);
if (! err)
break;
else if (err != GRUB_ERR_READ_ERROR)
return err;
}
else
err = grub_error (GRUB_ERR_READ_ERROR,
"disk missing");
k++;
if (k == array->total_devs)
k = 0;
}
if (! err)
break;
disknr++;
if (disknr == array->total_devs)
{
disknr = 0;
read_sector += ofs;
}
}
if (err)
return err;
buf += read_size << GRUB_DISK_SECTOR_BITS;
size -= read_size;
if (! size)
break;
b = 0;
disknr += (near - i);
while (disknr >= array->total_devs)
{
disknr -= array->total_devs;
read_sector += ofs;
}
}
break;
}
case 4:
case 5:
case 6:
{
grub_disk_addr_t read_sector;
grub_uint64_t b, p, n, disknr, e;
/* n = 1 for level 4 and 5, 2 for level 6. */
n = array->level / 3;
/* Find the first sector to read. */
read_sector = grub_divmod64 (sector, array->chunk_size, &b);
read_sector = grub_divmod64 (read_sector, array->total_devs - n,
&disknr);
if (array->level >= 5)
{
grub_divmod64 (read_sector, array->total_devs, &p);
if (! (array->layout & GRUB_RAID_LAYOUT_RIGHT_MASK))
p = array->total_devs - 1 - p;
if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK)
{
disknr += p + n;
}
else
{
grub_uint32_t q;
q = p + (n - 1);
if (q >= array->total_devs)
q -= array->total_devs;
if (disknr >= p)
disknr += n;
else if (disknr >= q)
disknr += q + 1;
}
if (disknr >= array->total_devs)
disknr -= array->total_devs;
}
else
p = array->total_devs - n;
read_sector *= array->chunk_size;
while (1)
{
grub_size_t read_size;
int next_level;
read_size = array->chunk_size - b;
if (read_size > size)
read_size = size;
e = 0;
if (array->members[disknr].device)
{
/* Reset read error. */
if (grub_errno == GRUB_ERR_READ_ERROR)
grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->members[disknr].device,
array->members[disknr].start_sector +
read_sector + b, 0,
read_size << GRUB_DISK_SECTOR_BITS,
buf);
if ((err) && (err != GRUB_ERR_READ_ERROR))
break;
e++;
}
else
err = GRUB_ERR_READ_ERROR;
if (err)
{
if (array->nr_devs < array->total_devs - n + e)
break;
grub_errno = GRUB_ERR_NONE;
if (array->level == 6)
{
err = ((grub_raid6_recover_func) ?
(*grub_raid6_recover_func) (array, disknr, p,
buf, read_sector + b,
read_size) :
grub_error (GRUB_ERR_BAD_DEVICE,
"raid6rec is not loaded"));
}
else
{
err = ((grub_raid5_recover_func) ?
(*grub_raid5_recover_func) (array, disknr,
buf, read_sector + b,
read_size) :
grub_error (GRUB_ERR_BAD_DEVICE,
"raid5rec is not loaded"));
}
if (err)
break;
}
buf += read_size << GRUB_DISK_SECTOR_BITS;
size -= read_size;
if (! size)
break;
b = 0;
disknr++;
if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK)
{
if (disknr == array->total_devs)
disknr = 0;
next_level = (disknr == p);
}
else
{
if (disknr == p)
disknr += n;
next_level = (disknr >= array->total_devs);
}
if (next_level)
{
read_sector += array->chunk_size;
if (array->level >= 5)
{
if (array->layout & GRUB_RAID_LAYOUT_RIGHT_MASK)
p = (p == array->total_devs - 1) ? 0 : p + 1;
else
p = (p == 0) ? array->total_devs - 1 : p - 1;
if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK)
{
disknr = p + n;
if (disknr >= array->total_devs)
disknr -= array->total_devs;
}
else
{
disknr -= array->total_devs;
if (disknr == p)
disknr += n;
}
}
else
disknr = 0;
}
}
}
break;
}
return err;
}
static grub_err_t
grub_raid_write (grub_disk_t disk __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;
}
static grub_err_t
insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_disk_addr_t start_sector, const char *scanner_name,
grub_raid_t raid __attribute__ ((unused)))
{
struct grub_raid_array *array = 0, *p;
int was_readable = 0;
/* See whether the device is part of an array we have already seen a
device from. */
for (p = array_list; p != NULL; p = p->next)
if ((p->uuid_len == new_array->uuid_len) &&
(! grub_memcmp (p->uuid, new_array->uuid, p->uuid_len)))
{
grub_free (new_array->uuid);
array = p;
was_readable = grub_is_array_readable (array);
/* Do some checks before adding the device to the array. */
if (new_array->index >= array->allocated_devs)
{
void *tmp;
unsigned int newnum = 2 * (new_array->index + 1);
tmp = grub_realloc (array->members, newnum
* sizeof (array->members[0]));
if (!tmp)
return grub_errno;
array->members = tmp;
grub_memset (array->members + array->allocated_devs,
0, (newnum - array->allocated_devs)
* sizeof (array->members[0]));
array->allocated_devs = newnum;
}
/* FIXME: Check whether the update time of the superblocks are
the same. */
if (array->total_devs == array->nr_devs)
/* We found more members of the array than the array
actually has according to its superblock. This shouldn't
happen normally. */
return grub_error (GRUB_ERR_BAD_DEVICE,
"superfluous RAID member (%d found)",
array->total_devs);
if (array->members[new_array->index].device != NULL)
/* We found multiple devices with the same number. Again,
this shouldn't happen. */
return grub_error (GRUB_ERR_BAD_DEVICE,
"found two disks with the index %d for RAID %s",
new_array->index, array->name);
if (new_array->disk_size < array->disk_size)
array->disk_size = new_array->disk_size;
break;
}
/* Add an array to the list if we didn't find any. */
if (!array)
{
array = grub_malloc (sizeof (*array));
if (!array)
{
grub_free (new_array->uuid);
return grub_errno;
}
*array = *new_array;
array->nr_devs = 0;
#ifdef GRUB_UTIL
array->driver = raid;
#endif
array->allocated_devs = 32;
if (new_array->index >= array->allocated_devs)
array->allocated_devs = 2 * (new_array->index + 1);
array->members = grub_zalloc (array->allocated_devs
* sizeof (array->members[0]));
if (!array->members)
{
grub_free (new_array->uuid);
return grub_errno;
}
if (! array->name)
{
for (p = array_list; p != NULL; p = p->next)
{
if (p->number == array->number)
break;
}
}
if (array->name || p)
{
/* The number is already in use, so we need to find a new one.
(Or, in the case of named arrays, the array doesn't have its
own number, but we need one that doesn't clash for use as a key
in the disk cache. */
int i = array->name ? 0x40000000 : 0;
while (1)
{
for (p = array_list; p != NULL; p = p->next)
{
if (p->number == i)
break;
}
if (! p)
{
/* We found an unused number. */
array->number = i;
break;
}
i++;
}
}
/* mdraid 1.x superblocks have only a name stored not a number.
Use it directly as GRUB device. */
if (! array->name)
{
array->name = grub_xasprintf ("md%d", array->number);
if (! array->name)
{
grub_free (array->members);
grub_free (array->uuid);
grub_free (array);
return grub_errno;
}
}
else
{
/* Strip off the homehost if present. */
char *colon = grub_strchr (array->name, ':');
char *new_name = grub_xasprintf ("md/%s",
colon ? colon + 1 : array->name);
if (! new_name)
{
grub_free (array->members);
grub_free (array->uuid);
grub_free (array);
return grub_errno;
}
grub_free (array->name);
array->name = new_name;
}
grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
scanner_name);
#ifdef GRUB_UTIL
grub_util_info ("Found array %s (%s)", array->name,
scanner_name);
#endif
{
int max_used_number = 0, len, need_new_name = 0;
int add_us = 0;
len = grub_strlen (array->name);
if (len && grub_isdigit (array->name[len-1]))
add_us = 1;
for (p = array_list; p != NULL; p = p->next)
{
int cur_num;
char *num, *end;
if (grub_strncmp (p->name, array->name, len) != 0)
continue;
if (p->name[len] == 0)
{
need_new_name = 1;
continue;
}
if (add_us && p->name[len] != '_')
continue;
if (add_us)
num = p->name + len + 1;
else
num = p->name + len;
if (!grub_isdigit (num[0]))
continue;
cur_num = grub_strtoull (num, &end, 10);
if (end[0])
continue;
if (cur_num > max_used_number)
max_used_number = cur_num;
}
if (need_new_name)
{
char *tmp;
tmp = grub_xasprintf ("%s%s%d", array->name, add_us ? "_" : "",
max_used_number + 1);
if (!tmp)
return grub_errno;
grub_free (array->name);
array->name = tmp;
}
}
/* Add our new array to the list. */
array->next = array_list;
array_list = array;
/* RAID 1 doesn't use a chunksize but code assumes one so set
one. */
if (array->level == 1)
array->chunk_size = 64;
}
/* Add the device to the array. */
array->members[new_array->index].device = disk;
array->members[new_array->index].start_sector = start_sector;
array->nr_devs++;
if (!was_readable && grub_is_array_readable (array))
array->became_readable_at = inscnt++;
return 0;
}
static void
free_array (void)
{
struct grub_raid_array *array;
array = array_list;
while (array)
{
struct grub_raid_array *p;
unsigned int i;
p = array;
array = array->next;
for (i = 0; i < p->allocated_devs; i++)
if (p->members[i].device)
grub_disk_close (p->members[i].device);
grub_free (p->members);
grub_free (p->uuid);
grub_free (p->name);
grub_free (p);
}
array_list = 0;
}
void
grub_raid_register (grub_raid_t raid)
{
raid->next = grub_raid_list;
grub_raid_list = raid;
}
void
grub_raid_unregister (grub_raid_t raid)
{
grub_raid_t *p, q;
for (p = &grub_raid_list, q = *p; q; p = &(q->next), q = q->next)
if (q == raid)
{
*p = q->next;
break;
}
}
static struct grub_disk_dev grub_raid_dev =
{
.name = "raid",
.id = GRUB_DISK_DEVICE_RAID_ID,
.iterate = grub_raid_iterate,
.open = grub_raid_open,
.close = grub_raid_close,
.read = grub_raid_read,
.write = grub_raid_write,
#ifdef GRUB_UTIL
.memberlist = grub_raid_memberlist,
.raidname = grub_raid_getname,
#endif
.next = 0
};
GRUB_MOD_INIT(raid)
{
grub_disk_dev_register (&grub_raid_dev);
}
GRUB_MOD_FINI(raid)
{
grub_disk_dev_unregister (&grub_raid_dev);
free_array ();
}

View file

@ -22,12 +22,13 @@
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
#include <grub/diskfilter.h>
#include <grub/crypto.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t
grub_raid5_recover (struct grub_raid_array *array, int disknr,
grub_raid5_recover (struct grub_diskfilter_segment *array, int disknr,
char *buf, grub_disk_addr_t sector, int size)
{
char *buf2;
@ -40,16 +41,15 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
grub_memset (buf, 0, size);
for (i = 0; i < (int) array->total_devs; i++)
for (i = 0; i < (int) array->node_count; i++)
{
grub_err_t err;
if (i == disknr)
continue;
err = grub_disk_read (array->members[i].device,
array->members[i].start_sector + sector,
0, size, buf2);
err = grub_diskfilter_read_node (&array->nodes[i], sector,
size >> GRUB_DISK_SECTOR_BITS, buf2);
if (err)
{
@ -57,7 +57,7 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
return err;
}
grub_raid_block_xor (buf, buf2, size);
grub_crypto_xor (buf, buf, buf2, size);
}
grub_free (buf2);

View file

@ -22,75 +22,49 @@
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
#include <grub/diskfilter.h>
#include <grub/crypto.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint8_t raid6_table1[256][256];
static grub_uint8_t raid6_table2[256][256];
/* x**y. */
static grub_uint8_t powx[255 * 2];
/* Such an s that x**s = y */
static int powx_inv[256];
static const grub_uint8_t poly = 0x1d;
static void
grub_raid_block_mul (grub_uint8_t mul, char *buf, int size)
grub_raid_block_mulx (int mul, char *buf, int size)
{
int i;
grub_uint8_t *p;
p = (grub_uint8_t *) buf;
for (i = 0; i < size; i++, p++)
*p = raid6_table1[mul][*p];
if (*p)
*p = powx[mul + powx_inv[*p]];
}
static void
grub_raid6_init_table (void)
{
int i, j;
int i;
for (i = 0; i < 256; i++)
raid6_table1[i][1] = raid6_table1[1][i] = i;
for (i = 2; i < 256; i++)
for (j = i; j < 256; j++)
{
int n;
grub_uint8_t c;
n = i >> 1;
c = raid6_table1[n][j];
c = (c << 1) ^ ((c & 0x80) ? 0x1d : 0);
if (i & 1)
c ^= j;
raid6_table1[j][i] = raid6_table1[i][j] = c;
}
raid6_table2[0][0] = 1;
for (i = 1; i < 256; i++)
raid6_table2[i][i] = raid6_table1[raid6_table2[i - 1][i - 1]][2];
for (i = 0; i < 254; i++)
for (j = 0; j < 254; j++)
{
grub_uint8_t c, n;
int k;
if (i == j)
continue;
k = i - j;
if (k < 0)
k += 255;
c = n = raid6_table2[k][k] ^ 1;
for (k = 0; k < 253; k++)
c = raid6_table1[c][n];
raid6_table2[i][j] = raid6_table1[raid6_table2[255 - j][255 - j]][c];
}
grub_uint8_t cur = 1;
for (i = 0; i < 255; i++)
{
powx[i] = cur;
powx[i + 255] = cur;
powx_inv[cur] = i;
if (cur & 0x80)
cur = (cur << 1) ^ poly;
else
cur <<= 1;
}
}
static grub_err_t
grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p,
char *buf, grub_disk_addr_t sector, int size)
{
int i, q, pos;
@ -107,27 +81,30 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
goto quit;
q = p + 1;
if (q == (int) array->total_devs)
if (q == (int) array->node_count)
q = 0;
pos = q + 1;
if (pos == (int) array->total_devs)
if (pos == (int) array->node_count)
pos = 0;
for (i = 0; i < (int) array->total_devs - 2; i++)
for (i = 0; i < (int) array->node_count - 2; i++)
{
int c;
if (array->layout & GRUB_RAID_LAYOUT_MUL_FROM_POS)
c = pos;
else
c = i;
if (pos == disknr)
bad1 = i;
bad1 = c;
else
{
if ((array->members[pos].device) &&
(! grub_disk_read (array->members[pos].device,
array->members[i].start_sector + sector,
0, size, buf)))
if (! grub_diskfilter_read_node (&array->nodes[pos], sector,
size >> GRUB_DISK_SECTOR_BITS, buf))
{
grub_raid_block_xor (pbuf, buf, size);
grub_raid_block_mul (raid6_table2[i][i], buf, size);
grub_raid_block_xor (qbuf, buf, size);
grub_crypto_xor (pbuf, pbuf, buf, size);
grub_raid_block_mulx (c, buf, size);
grub_crypto_xor (qbuf, qbuf, buf, size);
}
else
{
@ -135,13 +112,13 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
if (bad2 >= 0)
goto quit;
bad2 = i;
bad2 = c;
grub_errno = GRUB_ERR_NONE;
}
}
pos++;
if (pos == (int) array->total_devs)
if (pos == (int) array->node_count)
pos = 0;
}
@ -152,62 +129,46 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
if (bad2 < 0)
{
/* One bad device */
if ((array->members[p].device) &&
(! grub_disk_read (array->members[p].device,
array->members[i].start_sector + sector,
0, size, buf)))
if ((! grub_diskfilter_read_node (&array->nodes[p], sector,
size >> GRUB_DISK_SECTOR_BITS, buf)))
{
grub_raid_block_xor (buf, pbuf, size);
goto quit;
}
if (! array->members[q].device)
{
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
grub_crypto_xor (buf, buf, pbuf, size);
goto quit;
}
grub_errno = GRUB_ERR_NONE;
if (grub_disk_read (array->members[q].device,
array->members[i].start_sector + sector, 0, size, buf))
if (grub_diskfilter_read_node (&array->nodes[q], sector,
size >> GRUB_DISK_SECTOR_BITS, buf))
goto quit;
grub_raid_block_xor (buf, qbuf, size);
grub_raid_block_mul (raid6_table2[255 - bad1][255 - bad1], buf,
grub_crypto_xor (buf, buf, qbuf, size);
grub_raid_block_mulx (255 - bad1, buf,
size);
}
else
{
/* Two bad devices */
grub_uint8_t c;
int c;
if ((! array->members[p].device) || (! array->members[q].device))
{
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
goto quit;
}
if (grub_disk_read (array->members[p].device,
array->members[i].start_sector + sector,
0, size, buf))
if (grub_diskfilter_read_node (&array->nodes[p], sector,
size >> GRUB_DISK_SECTOR_BITS, buf))
goto quit;
grub_raid_block_xor (pbuf, buf, size);
grub_crypto_xor (pbuf, pbuf, buf, size);
if (grub_disk_read (array->members[q].device,
array->members[i].start_sector + sector,
0, size, buf))
if (grub_diskfilter_read_node (&array->nodes[q], sector,
size >> GRUB_DISK_SECTOR_BITS, buf))
goto quit;
grub_raid_block_xor (qbuf, buf, size);
grub_crypto_xor (qbuf, qbuf, buf, size);
c = raid6_table2[bad2][bad1];
grub_raid_block_mul (c, qbuf, size);
c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255;
grub_raid_block_mulx (c, qbuf, size);
c = raid6_table1[raid6_table2[bad2][bad2]][c];
grub_raid_block_mul (c, pbuf, size);
c = (bad2 + c) % 255;
grub_raid_block_mulx (c, pbuf, size);
grub_raid_block_xor (pbuf, qbuf, size);
grub_crypto_xor (pbuf, pbuf, qbuf, size);
grub_memcpy (buf, pbuf, size);
}

View file

@ -153,14 +153,14 @@ grub_scsi_inquiry (grub_scsi_t scsi)
/* Read the capacity and block size of SCSI. */
static grub_err_t
grub_scsi_read_capacity (grub_scsi_t scsi)
grub_scsi_read_capacity10 (grub_scsi_t scsi)
{
struct grub_scsi_read_capacity rc;
struct grub_scsi_read_capacity_data rcd;
struct grub_scsi_read_capacity10 rc;
struct grub_scsi_read_capacity10_data rcd;
grub_err_t err;
grub_err_t err_sense;
rc.opcode = grub_scsi_cmd_read_capacity;
rc.opcode = grub_scsi_cmd_read_capacity10;
rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
rc.logical_block_addr = 0;
rc.reserved1 = 0;
@ -182,7 +182,42 @@ grub_scsi_read_capacity (grub_scsi_t scsi)
if (err)
return err;
scsi->size = grub_be_to_cpu32 (rcd.size);
scsi->last_block = grub_be_to_cpu32 (rcd.last_block);
scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);
return GRUB_ERR_NONE;
}
/* Read the capacity and block size of SCSI. */
static grub_err_t
grub_scsi_read_capacity16 (grub_scsi_t scsi)
{
struct grub_scsi_read_capacity16 rc;
struct grub_scsi_read_capacity16_data rcd;
grub_err_t err;
grub_err_t err_sense;
rc.opcode = grub_scsi_cmd_read_capacity16;
rc.lun = (scsi->lun << GRUB_SCSI_LUN_SHIFT) | 0x10;
rc.logical_block_addr = 0;
rc.alloc_len = grub_cpu_to_be32 (sizeof (rcd));
rc.PMI = 0;
rc.control = 0;
err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc,
sizeof (rcd), (char *) &rcd);
/* Each SCSI command should be followed by Request Sense.
If not so, many devices STALLs or definitely freezes. */
err_sense = grub_scsi_request_sense (scsi);
if (err_sense != GRUB_ERR_NONE)
grub_errno = err;
/* err_sense is ignored for now and Request Sense Data also... */
if (err)
return err;
scsi->last_block = grub_be_to_cpu64 (rcd.last_block);
scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);
return GRUB_ERR_NONE;
@ -253,12 +288,43 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector,
return err;
}
#if 0
/* Send a SCSI request for DISK: read SIZE sectors starting with
sector SECTOR to BUF. */
static grub_err_t
grub_scsi_read16 (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_scsi_t scsi;
struct grub_scsi_read16 rd;
grub_err_t err;
grub_err_t err_sense;
scsi = disk->data;
rd.opcode = grub_scsi_cmd_read16;
rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
rd.lba = grub_cpu_to_be64 (sector);
rd.size = grub_cpu_to_be32 (size);
rd.reserved = 0;
rd.control = 0;
err = scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf);
/* Each SCSI command should be followed by Request Sense.
If not so, many devices STALLs or definitely freezes. */
err_sense = grub_scsi_request_sense (scsi);
if (err_sense != GRUB_ERR_NONE)
grub_errno = err;
/* err_sense is ignored for now and Request Sense Data also... */
return err;
}
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
sectors starting with SECTOR. */
static grub_err_t
grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
grub_size_t size, const char *buf)
{
grub_scsi_t scsi;
struct grub_scsi_write10 wr;
@ -287,6 +353,8 @@ grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector,
return err;
}
#if 0
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
sectors starting with SECTOR. */
static grub_err_t
@ -320,6 +388,39 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
}
#endif
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
sectors starting with SECTOR. */
static grub_err_t
grub_scsi_write16 (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, const char *buf)
{
grub_scsi_t scsi;
struct grub_scsi_write16 wr;
grub_err_t err;
grub_err_t err_sense;
scsi = disk->data;
wr.opcode = grub_scsi_cmd_write16;
wr.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
wr.lba = grub_cpu_to_be64 (sector);
wr.size = grub_cpu_to_be32 (size);
wr.reserved = 0;
wr.control = 0;
err = scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf);
/* Each SCSI command should be followed by Request Sense.
If not so, many devices STALLs or definitely freezes. */
err_sense = grub_scsi_request_sense (scsi);
if (err_sense != GRUB_ERR_NONE)
grub_errno = err;
/* err_sense is ignored for now and Request Sense Data also... */
return err;
}
static int
grub_scsi_iterate (int (*hook) (const char *name),
@ -475,15 +576,26 @@ grub_scsi_open (const char *name, grub_disk_t disk)
grub_errno = GRUB_ERR_NONE;
/* Read capacity of media */
err = grub_scsi_read_capacity (scsi);
err = grub_scsi_read_capacity10 (scsi);
if (err)
{
grub_free (scsi);
grub_dprintf ("scsi", "READ CAPACITY failed\n");
grub_dprintf ("scsi", "READ CAPACITY10 failed\n");
return err;
}
disk->total_sectors = scsi->size;
if (scsi->last_block == 0xffffffff)
{
err = grub_scsi_read_capacity16 (scsi);
if (err)
{
grub_free (scsi);
grub_dprintf ("scsi", "READ CAPACITY16 failed\n");
return err;
}
}
disk->total_sectors = scsi->last_block + 1;
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
{
grub_free (scsi);
@ -491,11 +603,11 @@ grub_scsi_open (const char *name, grub_disk_t disk)
scsi->blocksize);
}
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < scsi->blocksize;
(1U << disk->log_sector_size) < scsi->blocksize;
disk->log_sector_size++);
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
scsi->size, scsi->blocksize);
grub_dprintf ("scsi", "last_block=%" PRIuGRUB_UINT64_T ", blocksize=%u\n",
scsi->last_block, scsi->blocksize);
grub_dprintf ("scsi", "Disk total sectors = %llu\n",
(unsigned long long) disk->total_sectors);
@ -539,13 +651,19 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
switch (scsi->devtype)
{
case grub_scsi_devtype_direct:
err = grub_scsi_read10 (disk, sector, len, buf);
if (sector >> 32)
err = grub_scsi_read16 (disk, sector, len, buf);
else
err = grub_scsi_read10 (disk, sector, len, buf);
if (err)
return err;
break;
case grub_scsi_devtype_cdrom:
err = grub_scsi_read12 (disk, sector, len, buf);
if (sector >> 32)
err = grub_scsi_read16 (disk, sector, len, buf);
else
err = grub_scsi_read12 (disk, sector, len, buf);
if (err)
return err;
break;
@ -595,13 +713,41 @@ grub_scsi_write (grub_disk_t disk __attribute((unused)),
grub_size_t size __attribute((unused)),
const char *buf __attribute((unused)))
{
#if 0
/* XXX: Not tested yet! */
grub_scsi_t scsi;
/* XXX: This should depend on the device type? */
return grub_scsi_write10 (disk, sector, size, buf);
#endif
return GRUB_ERR_NOT_IMPLEMENTED_YET;
scsi = disk->data;
if (scsi->devtype == grub_scsi_devtype_cdrom)
return grub_error (GRUB_ERR_IO, "no CD burning");
while (size)
{
/* PATA doesn't support more than 32K reads.
Not sure about AHCI and USB. If it's confirmed that either of
them can do bigger reads reliably this value can be moved to 'scsi'
structure. */
grub_size_t len = 32768 >> disk->log_sector_size;
grub_err_t err;
if (len > size)
len = size;
/* Depending on the type, select a read function. */
switch (scsi->devtype)
{
case grub_scsi_devtype_direct:
if (sector >> 32)
err = grub_scsi_write16 (disk, sector, len, buf);
else
err = grub_scsi_write10 (disk, sector, len, buf);
if (err)
return err;
break;
}
size -= len;
sector += len;
buf += len << disk->log_sector_size;
}
return GRUB_ERR_NONE;
}

View file

@ -388,9 +388,9 @@ grub_usbms_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
static grub_err_t
grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
grub_size_t size, char *buf)
grub_size_t size, const char *buf)
{
return grub_usbms_transfer (scsi, cmdsize, cmd, size, buf, 1);
return grub_usbms_transfer (scsi, cmdsize, cmd, size, (char *) buf, 1);
}
static grub_err_t

View file

@ -26,7 +26,7 @@
#define bit_LM (1 << 29)
char *
const char *
grub_efiemu_get_default_core_name (void)
{

View file

@ -149,7 +149,8 @@ grub_efiemu_register_configuration_table (grub_efi_guid_t guid,
if (! get_table && ! data)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"you must set at least get_table or data");
if ((err = grub_efiemu_unregister_configuration_table (guid)))
err = grub_efiemu_unregister_configuration_table (guid);
if (err)
return err;
tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl));
@ -226,7 +227,7 @@ grub_efiemu_autocore (void)
{
const char *prefix;
char *filename;
char *suffix;
const char *suffix;
grub_err_t err;
if (grub_efiemu_sizeof_uintn_t () != 0)

View file

@ -201,10 +201,10 @@ efiemu_alloc_requests (void)
- (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE);
if (align_overhead == GRUB_EFIEMU_PAGESIZE)
align_overhead = 0;
curptr = ((grub_uint8_t *)curptr) + align_overhead;
curptr = ((grub_uint8_t *) curptr) + align_overhead;
/* Add the region to memory map */
grub_efiemu_add_to_mmap (PTR_TO_UINT64 (typestart),
grub_efiemu_add_to_mmap ((grub_addr_t) typestart,
curptr - typestart, reqorder[i]);
}
@ -404,7 +404,8 @@ grub_efiemu_mmap_fill (void)
GRUB_EFI_ACPI_MEMORY_NVS);
default:
grub_printf ("Unknown memory type %d. Assuming unusable\n", type);
grub_dprintf ("efiemu",
"Unknown memory type %d. Assuming unusable\n", type);
case GRUB_MEMORY_RESERVED:
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_UNUSABLE_MEMORY);

View file

@ -97,10 +97,9 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
grub_memcpy (&(conftables[i].vendor_guid), &(cur->guid),
sizeof (cur->guid));
if (cur->get_table)
conftables[i].vendor_table
= PTR_TO_UINT64 (cur->get_table (cur->data));
conftables[i].vendor_table = (grub_addr_t) cur->get_table (cur->data);
else
conftables[i].vendor_table = PTR_TO_UINT64 (cur->data);
conftables[i].vendor_table = (grub_addr_t) cur->data;
}
err = SUFFIX (grub_efiemu_crc) ();

View file

@ -21,6 +21,12 @@
As it emulates only runtime serviceit isn't able
to chainload EFI bootloader on non-EFI system (TODO) */
#ifdef __i386__
#include <grub/i386/types.h>
#else
#include <grub/x86_64/types.h>
#endif
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/efi/api.h>
@ -369,16 +375,16 @@ grub_efi_status_t EFI_FUNC
switch (cur_relloc->size)
{
case 8:
*((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
case 4:
*((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
case 2:
*((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
case 1:
*((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
}
}

View file

@ -169,7 +169,7 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
else
ptv_rels[ptv_written].plustype = 0;
ptv_rels[ptv_written].addr = PTR_TO_UINT64 (addr);
ptv_rels[ptv_written].addr = (grub_addr_t) addr;
ptv_rels[ptv_written].size = size;
ptv_written++;
@ -179,10 +179,10 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
/* Compute the value */
if (minus_handle)
value -= PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (minus_handle));
value -= (grub_addr_t) grub_efiemu_mm_obtain_request (minus_handle);
if (plus_handle)
value += PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (plus_handle));
value += (grub_addr_t) grub_efiemu_mm_obtain_request (plus_handle);
/* Write the value */
switch (size)
@ -248,16 +248,16 @@ grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
switch (cur_relloc->size)
{
case 8:
*((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
case 4:
*((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
case 2:
*((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
case 1:
*((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
}
}

View file

@ -250,8 +250,7 @@ open_section (grub_file_t file, struct font_file_section *section)
}
else if (retval < 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"font format error: can't read section name");
/* Read error. */
return 1;
}
@ -265,8 +264,7 @@ open_section (grub_file_t file, struct font_file_section *section)
}
else if (retval < 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"font format error: can't read section length");
/* Read error. */
return 1;
}
@ -608,7 +606,7 @@ grub_font_load (const char *filename)
if (!font->name)
{
grub_printf ("Note: Font has no name.\n");
grub_dprintf ("font", "Font has no name.\n");
font->name = grub_strdup ("Unknown");
}

View file

@ -49,7 +49,7 @@ lsfonts_command (grub_command_t cmd __attribute__ ((unused)),
{
struct grub_font_node *node;
grub_printf ("Loaded fonts:\n");
grub_puts_ (N_("Loaded fonts:"));
for (node = grub_font_list; node; node = node->next)
{
grub_font_t font = node->value;

View file

@ -25,6 +25,7 @@
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/charset.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -85,19 +86,19 @@ struct grub_affs_file
#define GRUB_AFFS_BLOCKPTR_OFFSET 24
#define GRUB_AFFS_SYMLINK_OFFSET 24
#define GRUB_AFFS_SYMLINK_SIZE(blocksize) ((blocksize) - 225)
#define GRUB_AFFS_FILETYPE_DIR -3
#define GRUB_AFFS_FILETYPE_REG 2
#define GRUB_AFFS_FILETYPE_REG 0xfffffffd
#define GRUB_AFFS_FILETYPE_DIR 2
#define GRUB_AFFS_FILETYPE_SYMLINK 3
struct grub_fshelp_node
{
struct grub_affs_data *data;
grub_disk_addr_t block;
grub_uint32_t block;
struct grub_fshelp_node *parent;
struct grub_affs_file di;
grub_uint32_t *block_cache;
grub_uint32_t last_block_cache;
};
/* Information about a "mounted" affs filesystem. */
@ -120,32 +121,46 @@ static grub_dl_t my_mod;
static grub_disk_addr_t
grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
int links;
grub_uint32_t target, curblock;
grub_uint32_t pos;
int block = node->block;
struct grub_affs_file file;
struct grub_affs_data *data = node->data;
grub_uint64_t mod;
if (!node->block_cache)
{
node->block_cache = grub_malloc ((((grub_be_to_cpu32 (node->di.size)
+ 511) >> 9) / data->htsize + 1)
* sizeof (node->block_cache[0]));
if (!node->block_cache)
return -1;
node->last_block_cache = 0;
node->block_cache[0] = node->block;
}
/* Files are at most 2G on AFFS, so no need for 64-bit division. */
target = (grub_uint32_t) fileblock / data->htsize;
mod = (grub_uint32_t) fileblock % data->htsize;
/* Find the block that points to the fileblock we are looking up by
following the chain until the right table is reached. */
for (links = grub_divmod64 (fileblock, data->htsize, &mod); links; links--)
for (curblock = node->last_block_cache + 1; curblock <= target; curblock++)
{
grub_disk_read (data->disk, block + data->blocksize - 1,
grub_disk_read (data->disk,
node->block_cache[curblock - 1] + data->blocksize - 1,
data->blocksize * (GRUB_DISK_SECTOR_SIZE
- GRUB_AFFS_FILE_LOCATION),
sizeof (file), &file);
if (grub_errno)
return 0;
block = grub_be_to_cpu32 (file.extension);
node->block_cache[curblock] = grub_be_to_cpu32 (file.extension);
node->last_block_cache = curblock;
}
/* Translate the fileblock to the block within the right table. */
fileblock = mod;
grub_disk_read (data->disk, block,
grub_disk_read (data->disk, node->block_cache[target],
GRUB_AFFS_BLOCKPTR_OFFSET
+ (data->htsize - fileblock - 1) * sizeof (pos),
+ (data->htsize - mod - 1) * sizeof (pos),
sizeof (pos), &pos);
if (grub_errno)
return 0;
@ -153,21 +168,6 @@ grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
return grub_be_to_cpu32 (pos);
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_affs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
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,
grub_be_to_cpu32 (node->di.size), 0);
}
static struct grub_affs_data *
grub_affs_mount (grub_disk_t disk)
{
@ -178,7 +178,7 @@ grub_affs_mount (grub_disk_t disk)
int checksum = 0;
int blocksize = 0;
data = grub_malloc (sizeof (struct grub_affs_data));
data = grub_zalloc (sizeof (struct grub_affs_data));
if (!data)
return 0;
@ -202,12 +202,6 @@ grub_affs_mount (grub_disk_t disk)
goto fail;
}
/* Read the bootblock. */
grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
&data->bblock);
if (grub_errno)
goto fail;
/* No sane person uses more than 8KB for a block. At least I hope
for that person because in that case this won't work. */
rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16);
@ -270,18 +264,21 @@ grub_affs_read_symlink (grub_fshelp_node_t node)
{
struct grub_affs_data *data = node->data;
char *symlink;
const grub_size_t symlink_size = (data->blocksize * GRUB_DISK_SECTOR_SIZE
- 225);
symlink = grub_malloc (GRUB_AFFS_SYMLINK_SIZE (data->blocksize));
symlink = grub_malloc (symlink_size + 1);
if (!symlink)
return 0;
grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET,
GRUB_AFFS_SYMLINK_SIZE (data->blocksize), symlink);
symlink_size, symlink);
if (grub_errno)
{
grub_free (symlink);
return 0;
}
symlink[symlink_size] = 1;
grub_dprintf ("affs", "Symlink: `%s'\n", symlink);
return symlink;
}
@ -300,25 +297,26 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
struct grub_affs_data *data = dir->data;
grub_uint32_t *hashtable;
auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
grub_disk_addr_t block,
auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
const struct grub_affs_file *fil);
int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
grub_disk_addr_t block,
int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
const struct grub_affs_file *fil)
{
int type;
node = grub_malloc (sizeof (*node));
grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1];
grub_size_t len;
node = grub_zalloc (sizeof (*node));
if (!node)
{
grub_free (hashtable);
return 1;
}
if ((int) grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR)
if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG)
type = GRUB_FSHELP_REG;
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG)
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR)
type = GRUB_FSHELP_DIR;
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK)
type = GRUB_FSHELP_SYMLINK;
@ -330,7 +328,12 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
node->di = *fil;
node->parent = dir;
if (hook (name, type, node))
len = fil->namelen;
if (len > sizeof (fil->name))
len = sizeof (fil->name);
*grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0';
if (hook ((char *) name_u8, type, node))
{
grub_free (hashtable);
return 1;
@ -339,7 +342,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
}
/* Create the directory entries for `.' and `..'. */
node = grub_malloc (sizeof (*node));
node = grub_zalloc (sizeof (*node));
if (!node)
return 1;
@ -348,7 +351,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
return 1;
if (dir->parent)
{
node = grub_malloc (sizeof (*node));
node = grub_zalloc (sizeof (*node));
if (!node)
return 1;
*node = *dir->parent;
@ -356,7 +359,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
return 1;
}
hashtable = grub_malloc (data->htsize * sizeof (*hashtable));
hashtable = grub_zalloc (data->htsize * sizeof (*hashtable));
if (!hashtable)
return 1;
@ -367,7 +370,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
for (i = 0; i < data->htsize; i++)
{
grub_uint64_t next;
grub_uint32_t next;
if (!hashtable[i])
continue;
@ -385,9 +388,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
if (grub_errno)
goto fail;
file.name[file.namelen] = '\0';
if (grub_affs_create_node ((char *) (file.name), next, &file))
if (grub_affs_create_node (next, &file))
return 1;
next = grub_be_to_cpu32 (file.next);
@ -441,10 +442,13 @@ grub_affs_open (struct grub_file *file, const char *name)
return grub_errno;
}
static grub_err_t
grub_affs_close (grub_file_t file)
{
struct grub_affs_data *data =
(struct grub_affs_data *) file->data;
grub_free (data->diropen.block_cache);
grub_free (file->data);
grub_dl_unref (my_mod);
@ -452,7 +456,6 @@ grub_affs_close (grub_file_t file)
return GRUB_ERR_NONE;
}
/* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t
grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
@ -460,13 +463,12 @@ grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
struct grub_affs_data *data =
(struct grub_affs_data *) file->data;
int size = grub_affs_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
return size;
return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen,
file->read_hook,
file->offset, len, buf, grub_affs_read_block,
grub_be_to_cpu32 (data->diropen.di.size), 0);
}
static grub_err_t
grub_affs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
@ -531,6 +533,7 @@ grub_affs_label (grub_device_t device, char **label)
data = grub_affs_mount (disk);
if (data)
{
grub_size_t len;
/* The rootblock maps quite well on a file header block, it's
something we can use here. */
grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock),
@ -540,7 +543,12 @@ grub_affs_label (grub_device_t device, char **label)
if (grub_errno)
return 0;
*label = grub_strndup ((char *) (file.name), file.namelen);
len = file.namelen;
if (len > sizeof (file.name))
len = sizeof (file.name);
*label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
if (*label)
*grub_latin1_to_utf8 ((grub_uint8_t *) *label, file.name, len) = '\0';
}
else
*label = 0;

View file

@ -1,720 +1,3 @@
/* afs.c - The native AtheOS file-system. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#define MODE_AFS 1
#include "bfs.c"
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
GRUB_MOD_LICENSE ("GPLv3+");
#ifdef MODE_BIGENDIAN
#define GRUB_AFS_FSNAME_SUFFIX "_be"
#else
#define GRUB_AFS_FSNAME_SUFFIX ""
#endif
#ifdef MODE_BFS
#define GRUB_AFS_FSNAME "befs" GRUB_AFS_FSNAME_SUFFIX
#else
#define GRUB_AFS_FSNAME "afs" GRUB_AFS_FSNAME_SUFFIX
#endif
#define GRUB_AFS_DIRECT_BLOCK_COUNT 12
#define GRUB_AFS_BLOCKS_PER_DI_RUN 4
#ifdef MODE_BFS
#define GRUB_AFS_SBLOCK_SECTOR 1
#define GRUB_AFS_SBLOCK_MAGIC1 0x42465331 /* BFS1. */
#else
#define GRUB_AFS_SBLOCK_SECTOR 2
#define GRUB_AFS_SBLOCK_MAGIC1 0x41465331 /* AFS1. */
#endif
#define GRUB_AFS_SBLOCK_MAGIC2 0xdd121031
#define GRUB_AFS_SBLOCK_MAGIC3 0x15b6830e
#define GRUB_AFS_INODE_MAGIC 0x64358428
#ifdef MODE_BFS
#define GRUB_AFS_BTREE_MAGIC 0x69f6c2e8
#else
#define GRUB_AFS_BTREE_MAGIC 0x65768995
#endif
#define GRUB_AFS_BNODE_SIZE 1024
#define GRUB_AFS_S_IFMT 00170000
#define GRUB_AFS_S_IFLNK 0120000
#define GRUB_AFS_S_IFREG 0100000
#define GRUB_AFS_S_IFDIR 0040000
#define GRUB_AFS_S_IFIFO 0010000
#define GRUB_AFS_NULL_VAL ((grub_afs_bvalue_t)-1)
#ifdef MODE_BIGENDIAN
#define grub_afs_to_cpu16(x) grub_be_to_cpu16 (x)
#define grub_afs_to_cpu32(x) grub_be_to_cpu32 (x)
#define grub_afs_to_cpu64(x) grub_be_to_cpu64 (x)
#else
#define grub_afs_to_cpu16(x) grub_le_to_cpu16 (x)
#define grub_afs_to_cpu32(x) grub_le_to_cpu32 (x)
#define grub_afs_to_cpu64(x) grub_le_to_cpu64 (x)
#endif
#ifdef MODE_BFS
#define B_KEY_INDEX_ALIGN 8
#else
#define B_KEY_INDEX_ALIGN 4
#endif
#define B_KEY_INDEX_OFFSET(node) ((grub_uint16_t *) \
((char *) (node) \
+ ALIGN_UP (sizeof (struct grub_afs_bnode) \
+ node->key_size, \
B_KEY_INDEX_ALIGN)))
#define B_KEY_VALUE_OFFSET(node) ((grub_afs_bvalue_t *) \
((char *) B_KEY_INDEX_OFFSET (node) + \
node->key_count * 2))
typedef grub_uint64_t grub_afs_off_t;
typedef grub_uint64_t grub_afs_bigtime;
typedef grub_uint64_t grub_afs_bvalue_t;
struct grub_afs_blockrun
{
grub_uint32_t group;
grub_uint16_t start;
grub_uint16_t len;
} __attribute__ ((packed));
struct grub_afs_datastream
{
struct grub_afs_blockrun direct[GRUB_AFS_DIRECT_BLOCK_COUNT];
grub_afs_off_t max_direct_range;
struct grub_afs_blockrun indirect;
grub_afs_off_t max_indirect_range;
struct grub_afs_blockrun double_indirect;
grub_afs_off_t max_double_indirect_range;
grub_afs_off_t size;
} __attribute__ ((packed));
struct grub_afs_bnode
{
grub_afs_bvalue_t left;
grub_afs_bvalue_t right;
grub_afs_bvalue_t overflow;
#ifdef MODE_BFS
grub_uint16_t key_count;
grub_uint16_t key_size;
#else
grub_uint32_t key_count;
grub_uint32_t key_size;
#endif
char key_data[0];
} __attribute__ ((packed));
#ifdef MODE_BFS
struct grub_afs_btree
{
grub_uint32_t magic;
grub_uint32_t unused1;
grub_uint32_t tree_depth;
grub_uint32_t unused2;
grub_afs_bvalue_t root;
grub_uint32_t unused3[4];
} __attribute__ ((packed));
#else
struct grub_afs_btree
{
grub_uint32_t magic;
grub_afs_bvalue_t root;
grub_uint32_t tree_depth;
grub_afs_bvalue_t last_node;
grub_afs_bvalue_t first_free;
} __attribute__ ((packed));
#endif
/* Beware that following structure describes AtheFS and if you write code
which uses currently unused fields check it with both AtheFS and BeFS.
*/
struct grub_afs_sblock
{
char name[32];
grub_uint32_t magic1;
grub_uint32_t byte_order;
grub_uint32_t block_size;
grub_uint32_t block_shift;
grub_afs_off_t num_blocks;
grub_afs_off_t used_blocks;
grub_uint32_t inode_size;
grub_uint32_t magic2;
grub_uint32_t block_per_group; /* Number of blocks per allocation
group. (Max 65536) */
grub_uint32_t alloc_group_shift; /* Number of bits to shift a group
number to get a byte address. */
grub_uint32_t alloc_group_count;
grub_uint32_t flags;
struct grub_afs_blockrun log_block;
grub_afs_off_t log_start;
grub_uint32_t valid_log_blocks;
grub_uint32_t log_size;
grub_uint32_t magic3;
struct grub_afs_blockrun root_dir; /* Root dir inode. */
struct grub_afs_blockrun deleted_files; /* Directory containing files
scheduled for deletion. */
struct grub_afs_blockrun index_dir; /* Directory of index files. */
grub_uint32_t boot_loader_size;
grub_uint32_t pad[7];
} __attribute__ ((packed));
struct grub_afs_inode
{
grub_uint32_t magic1;
struct grub_afs_blockrun inode_num;
grub_uint32_t uid;
grub_uint32_t gid;
grub_uint32_t mode;
grub_uint32_t flags;
#ifndef MODE_BFS
grub_uint32_t link_count;
#endif
grub_afs_bigtime create_time;
grub_afs_bigtime modified_time;
struct grub_afs_blockrun parent;
struct grub_afs_blockrun attrib_dir;
grub_uint32_t index_type; /* Key data-key only used for index files. */
grub_uint32_t inode_size;
grub_uint32_t unused;
struct grub_afs_datastream stream;
grub_uint32_t pad[4];
grub_uint32_t small_data[1];
} __attribute__ ((packed));
struct grub_fshelp_node
{
struct grub_afs_data *data;
struct grub_afs_inode inode;
};
struct grub_afs_data
{
grub_disk_t disk;
struct grub_afs_sblock sblock;
struct grub_afs_inode *inode;
struct grub_fshelp_node diropen;
};
static grub_dl_t my_mod;
static grub_afs_off_t
grub_afs_run_to_num (struct grub_afs_sblock *sb,
struct grub_afs_blockrun *run)
{
return ((grub_afs_off_t) grub_afs_to_cpu32 (run->group)
* sb->block_per_group + grub_afs_to_cpu16 (run->start));
}
static grub_err_t
grub_afs_read_inode (struct grub_afs_data *data,
grub_uint32_t ino, struct grub_afs_inode *inode)
{
return grub_disk_read (data->disk,
ino *
(data->sblock.block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (struct grub_afs_inode),
inode);
}
static grub_disk_addr_t
grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
struct grub_afs_sblock *sb = &node->data->sblock;
struct grub_afs_datastream *ds = &node->inode.stream;
if (fileblock < grub_afs_to_cpu64 (ds->max_direct_range))
{
int i;
for (i = 0; i < GRUB_AFS_DIRECT_BLOCK_COUNT; i++)
{
if (fileblock < grub_afs_to_cpu16 (ds->direct[i].len))
return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock;
fileblock -= grub_afs_to_cpu16 (ds->direct[i].len);
}
}
else if (fileblock < grub_afs_to_cpu64 (ds->max_indirect_range))
{
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
struct grub_afs_blockrun indir[ptrs_per_blk];
grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect);
int i;
fileblock -= grub_afs_to_cpu64 (ds->max_direct_range);
for (i = 0; i < ds->indirect.len; i++, blk++)
{
int j;
if (grub_disk_read (node->data->disk,
blk * (sb->block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (indir),
indir))
return 0;
for (j = 0; j < ptrs_per_blk; j++)
{
if (fileblock < grub_afs_to_cpu16 (indir[j].len))
return grub_afs_run_to_num (sb, &indir[j]) + fileblock;
fileblock -= grub_afs_to_cpu16 (indir[j].len);
}
}
}
else
{
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
struct grub_afs_blockrun indir[ptrs_per_blk];
/* ([idblk][idptr]) ([dblk][dptr]) [blk] */
int cur_pos = fileblock - grub_afs_to_cpu64 (ds->max_indirect_range);
int dptr_size = GRUB_AFS_BLOCKS_PER_DI_RUN;
int dblk_size = dptr_size * ptrs_per_blk;
int idptr_size = dblk_size * GRUB_AFS_BLOCKS_PER_DI_RUN;
int idblk_size = idptr_size * ptrs_per_blk;
int off = cur_pos % GRUB_AFS_BLOCKS_PER_DI_RUN;
int dptr = (cur_pos / dptr_size) % ptrs_per_blk;
int dblk = (cur_pos / dblk_size) % GRUB_AFS_BLOCKS_PER_DI_RUN;
int idptr = (cur_pos / idptr_size) % ptrs_per_blk;
int idblk = (cur_pos / idblk_size);
if (grub_disk_read (node->data->disk,
(grub_afs_run_to_num (sb, &ds->double_indirect)
+ idblk) *
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (indir),
indir))
return 0;
if (grub_disk_read (node->data->disk,
(grub_afs_run_to_num (sb, &indir[idptr]) + dblk) *
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (indir),
indir))
return 0;
return grub_afs_run_to_num (sb, &indir[dptr]) + off;
}
return 0;
}
static grub_ssize_t
grub_afs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_afs_read_block,
grub_afs_to_cpu64 (node->inode.stream.size),
node->data->sblock.block_shift
- GRUB_DISK_SECTOR_BITS);
}
static char *
grub_afs_read_symlink (grub_fshelp_node_t node)
{
char *ret;
grub_afs_off_t size = grub_afs_to_cpu64 (node->inode.stream.size);
if (size == 0)
{
size = sizeof (node->inode.stream);
ret = grub_zalloc (size + 1);
if (! ret)
return 0;
grub_memcpy (ret, (char *) &(node->inode.stream),
sizeof (node->inode.stream));
return ret;
}
ret = grub_zalloc (size + 1);
if (! ret)
return 0;
grub_afs_read_file (node, 0, 0, size, ret);
return ret;
}
static int
grub_afs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_afs_btree head;
char node_data [GRUB_AFS_BNODE_SIZE];
struct grub_afs_bnode *node = (struct grub_afs_bnode *) node_data;
int i;
if ((dir->inode.stream.size == 0)
|| ((grub_afs_to_cpu32 (dir->inode.mode) & GRUB_AFS_S_IFMT)
!= GRUB_AFS_S_IFDIR))
return 0;
grub_afs_read_file (dir, 0, 0, sizeof (head), (char *) &head);
if (grub_errno)
return 0;
grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (head.root),
GRUB_AFS_BNODE_SIZE, (char *) node);
if (grub_errno)
return 0;
for (i = 0; i < (int) grub_afs_to_cpu32 (head.tree_depth) - 1; i++)
{
grub_afs_bvalue_t blk;
blk = grub_afs_to_cpu64(B_KEY_VALUE_OFFSET (node) [0]);
grub_afs_read_file (dir, 0, blk, GRUB_AFS_BNODE_SIZE, (char *) node);
if (grub_errno)
return 0;
}
if (node->key_count)
{
grub_uint32_t cur_key = 0;
while (1)
{
int key_start, key_size;
grub_uint16_t *index;
index = B_KEY_INDEX_OFFSET (node);
key_start = (cur_key > 0)
? grub_afs_to_cpu16 (index[cur_key - 1]) : 0;
key_size = grub_afs_to_cpu16 (index[cur_key]) - key_start;
if (key_size > 0)
{
char filename [key_size + 1];
struct grub_fshelp_node *fdiro;
int mode, type;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
if (! fdiro)
return 0;
fdiro->data = dir->data;
if (grub_afs_read_inode (dir->data,
grub_afs_to_cpu64
(B_KEY_VALUE_OFFSET (node) [cur_key]),
&fdiro->inode))
return 0;
grub_memcpy (filename, &node->key_data[key_start], key_size);
filename [key_size] = 0;
mode = (grub_afs_to_cpu32 (fdiro->inode.mode) & GRUB_AFS_S_IFMT);
if (mode == GRUB_AFS_S_IFDIR)
type = GRUB_FSHELP_DIR;
else if (mode == GRUB_AFS_S_IFREG)
type = GRUB_FSHELP_REG;
else if (mode == GRUB_AFS_S_IFLNK)
type = GRUB_FSHELP_SYMLINK;
else
type = GRUB_FSHELP_UNKNOWN;
if (hook (filename, type, fdiro))
return 1;
}
cur_key++;
if (cur_key >= grub_afs_to_cpu32 (node->key_count))
{
if (node->right == GRUB_AFS_NULL_VAL)
break;
grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (node->right),
GRUB_AFS_BNODE_SIZE, (char *) node);
if (grub_errno)
return 0;
cur_key = 0;
}
}
}
return 0;
}
static int
grub_afs_validate_sblock (struct grub_afs_sblock *sb)
{
if (grub_afs_to_cpu32 (sb->magic1) == GRUB_AFS_SBLOCK_MAGIC1)
{
sb->magic2 = grub_afs_to_cpu32 (sb->magic2);
sb->magic3 = grub_afs_to_cpu32 (sb->magic3);
sb->block_shift = grub_afs_to_cpu32 (sb->block_shift);
sb->block_size = grub_afs_to_cpu32 (sb->block_size);
sb->used_blocks = grub_afs_to_cpu64 (sb->used_blocks);
sb->num_blocks = grub_afs_to_cpu64 (sb->num_blocks);
sb->inode_size = grub_afs_to_cpu32 (sb->inode_size);
sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
sb->alloc_group_shift = grub_afs_to_cpu32 (sb->alloc_group_shift);
sb->block_per_group = grub_afs_to_cpu32 (sb->block_per_group);
sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
sb->log_size = grub_afs_to_cpu32 (sb->log_size);
}
else
return 0;
if ((sb->magic2 != GRUB_AFS_SBLOCK_MAGIC2) ||
(sb->magic3 != GRUB_AFS_SBLOCK_MAGIC3))
return 0;
#ifdef MODE_BFS
sb->block_per_group = 1 << (sb->alloc_group_shift);
#endif
if (((grub_uint32_t) (1 << sb->block_shift) != sb->block_size)
|| (sb->used_blocks > sb->num_blocks )
|| (sb->inode_size != sb->block_size)
|| (0 == sb->block_size)
#ifndef MODE_BFS
|| ((grub_uint32_t) (1 << sb->alloc_group_shift) !=
sb->block_per_group * sb->block_size)
|| (sb->alloc_group_count * sb->block_per_group < sb->num_blocks)
|| (grub_afs_to_cpu16 (sb->log_block.len) != sb->log_size)
|| (grub_afs_to_cpu32 (sb->valid_log_blocks) > sb->log_size)
#endif
)
return 0;
return 1;
}
static struct grub_afs_data *
grub_afs_mount (grub_disk_t disk)
{
struct grub_afs_data *data = 0;
data = grub_malloc (sizeof (struct grub_afs_data));
if (!data)
return 0;
/* Read the superblock. */
if (grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0,
sizeof (struct grub_afs_sblock), &data->sblock))
goto fail;
if (! grub_afs_validate_sblock (&data->sblock))
goto fail;
data->diropen.data = data;
data->inode = &data->diropen.inode;
data->disk = disk;
if (grub_afs_read_inode (data,
grub_afs_run_to_num (&data->sblock,
&data->sblock.root_dir),
data->inode))
goto fail;
return data;
fail:
grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem");
grub_free (data);
return 0;
}
static grub_err_t
grub_afs_open (struct grub_file *file, const char *name)
{
struct grub_afs_data *data;
struct grub_fshelp_node *fdiro = 0;
grub_dl_ref (my_mod);
data = grub_afs_mount (file->device->disk);
if (! data)
goto fail;
grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_afs_iterate_dir,
grub_afs_read_symlink, GRUB_FSHELP_REG);
if (grub_errno)
goto fail;
grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_afs_inode));
grub_free (fdiro);
file->size = grub_afs_to_cpu64 (data->inode->stream.size);
file->data = data;
file->offset = 0;
return 0;
fail:
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_ssize_t
grub_afs_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_afs_data *data = (struct grub_afs_data *) file->data;
return grub_afs_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
}
static grub_err_t
grub_afs_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_afs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_afs_data *data = 0;
struct grub_fshelp_node *fdiro = 0;
auto int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node);
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1;
#ifdef MODE_BFS
info.mtime = grub_afs_to_cpu64 (node->inode.modified_time) >> 16;
#else
info.mtime = grub_divmod64 (grub_afs_to_cpu64 (node->inode.modified_time),
1000000, 0);
#endif
grub_free (node);
return hook (filename, &info);
}
grub_dl_ref (my_mod);
data = grub_afs_mount (device->disk);
if (! data)
goto fail;
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_afs_iterate_dir,
grub_afs_read_symlink, GRUB_FSHELP_DIR);
if (grub_errno)
goto fail;
grub_afs_iterate_dir (fdiro, iterate);
if (fdiro != &data->diropen)
grub_free (fdiro);
fail:
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_afs_label (grub_device_t device, char **label)
{
struct grub_afs_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_afs_mount (disk);
if (data)
*label = grub_strndup (data->sblock.name, sizeof (data->sblock.name));
else
*label = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_afs_fs = {
.name = GRUB_AFS_FSNAME,
.dir = grub_afs_dir,
.open = grub_afs_open,
.read = grub_afs_read,
.close = grub_afs_close,
.label = grub_afs_label,
.next = 0
};
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
GRUB_MOD_INIT (befs_be)
#elif defined (MODE_BFS)
GRUB_MOD_INIT (befs)
#elif defined (MODE_BIGENDIAN)
GRUB_MOD_INIT (afs_be)
#else
GRUB_MOD_INIT (afs)
#endif
{
grub_fs_register (&grub_afs_fs);
my_mod = mod;
}
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
GRUB_MOD_FINI (befs_be)
#elif defined (MODE_BFS)
GRUB_MOD_FINI (befs)
#elif defined (MODE_BIGENDIAN)
GRUB_MOD_FINI (afs_be)
#else
GRUB_MOD_FINI (afs)
#endif
{
grub_fs_unregister (&grub_afs_fs);
}

View file

@ -1,3 +0,0 @@
/* befs.c - The native BeOS/Haiku file-system. */
#define MODE_BFS 1
#include "afs.c"

View file

@ -1,4 +0,0 @@
/* befs.c - The native BeOS/Haiku file-system. */
#define MODE_BFS 1
#define MODE_BIGENDIAN 1
#include "afs.c"

1050
grub-core/fs/bfs.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -26,22 +26,35 @@
#include <grub/types.h>
#include <grub/lib/crc.h>
#include <grub/deflate.h>
#include <minilzo.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_BTRFS_SIGNATURE "_BHRfS_M"
/* From http://www.oberhumer.com/opensource/lzo/lzofaq.php
* LZO will expand incompressible data by a little amount. I still haven't
* computed the exact values, but I suggest using these formulas for
* a worst-case expansion calculation:
*
* output_block_size = input_block_size + (input_block_size / 16) + 64 + 3
* */
#define GRUB_BTRFS_LZO_BLOCK_SIZE 4096
#define GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE (GRUB_BTRFS_LZO_BLOCK_SIZE + \
(GRUB_BTRFS_LZO_BLOCK_SIZE / 16) + 64 + 3)
typedef grub_uint8_t grub_btrfs_checksum_t[0x20];
typedef grub_uint16_t grub_btrfs_uuid_t[8];
struct grub_btrfs_device
{
grub_uint64_t device_id;
grub_uint8_t dummy[0x62 - 8];
grub_uint64_t size;
grub_uint8_t dummy[0x62 - 0x10];
} __attribute__ ((packed));
struct grub_btrfs_superblock
{
{
grub_btrfs_checksum_t checksum;
grub_btrfs_uuid_t uuid;
grub_uint8_t dummy[0x10];
@ -160,7 +173,8 @@ struct grub_btrfs_leaf_descriptor
{
unsigned depth;
unsigned allocated;
struct {
struct
{
grub_disk_addr_t addr;
unsigned iter;
unsigned maxiter;
@ -179,7 +193,7 @@ struct grub_btrfs_time
{
grub_int64_t sec;
grub_uint32_t nanosec;
} __attribute__ ((aligned(4)));
} __attribute__ ((aligned (4)));
struct grub_btrfs_inode
{
@ -215,12 +229,13 @@ struct grub_btrfs_extent_data
#define GRUB_BTRFS_COMPRESSION_NONE 0
#define GRUB_BTRFS_COMPRESSION_ZLIB 1
#define GRUB_BTRFS_COMPRESSION_LZO 2
#define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100
static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2,
256 * 1048576 * 2,
1048576ULL * 1048576ULL * 2 };
256 * 1048576 * 2, 1048576ULL * 1048576ULL * 2
};
static grub_err_t
grub_btrfs_read_logical (struct grub_btrfs_data *data,
@ -234,6 +249,10 @@ read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb)
for (i = 0; i < ARRAY_SIZE (superblock_sectors); i++)
{
struct grub_btrfs_superblock sblock;
/* Don't try additional superblocks beyond device size. */
if (i && (grub_le_to_cpu64 (sblock.this_device.size)
>> GRUB_DISK_SECTOR_BITS) <= superblock_sectors[i])
break;
err = grub_disk_read (disk, superblock_sectors[i], 0,
sizeof (sblock), &sblock);
if (err == GRUB_ERR_OUT_OF_RANGE)
@ -283,7 +302,7 @@ free_iterator (struct grub_btrfs_leaf_descriptor *desc)
}
static grub_err_t
save_ref (struct grub_btrfs_leaf_descriptor *desc,
save_ref (struct grub_btrfs_leaf_descriptor *desc,
grub_disk_addr_t addr, unsigned i, unsigned m, int l)
{
desc->depth++;
@ -307,7 +326,7 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc,
static int
next (struct grub_btrfs_data *data,
struct grub_btrfs_leaf_descriptor *desc,
grub_disk_addr_t *outaddr, grub_size_t *outsize,
grub_disk_addr_t * outaddr, grub_size_t * outsize,
struct grub_btrfs_key *key_out)
{
grub_err_t err;
@ -330,17 +349,17 @@ next (struct grub_btrfs_data *data,
err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter
* sizeof (node)
+ sizeof (struct btrfs_header)
+ desc->data[desc->depth - 1].addr, &node,
sizeof (node));
+ desc->data[desc->depth - 1].addr,
&node, sizeof (node));
if (err)
return -err;
err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr), &head,
sizeof (head));
err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr),
&head, sizeof (head));
if (err)
return -err;
save_ref (desc, grub_le_to_cpu64 (node.addr), 0,
save_ref (desc, grub_le_to_cpu64 (node.addr), 0,
grub_le_to_cpu32 (head.nitems), !head.level);
}
err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter
@ -354,12 +373,12 @@ next (struct grub_btrfs_data *data,
*outaddr = desc->data[desc->depth - 1].addr + sizeof (struct btrfs_header)
+ grub_le_to_cpu32 (leaf.offset);
*key_out = leaf.key;
return 1;
return 1;
}
static grub_err_t
lower_bound (struct grub_btrfs_data *data,
const struct grub_btrfs_key *key_in,
const struct grub_btrfs_key *key_in,
struct grub_btrfs_key *key_out,
grub_disk_addr_t root,
grub_disk_addr_t *outaddr, grub_size_t *outsize,
@ -410,8 +429,9 @@ lower_bound (struct grub_btrfs_data *data,
grub_dprintf ("btrfs",
"internal node (depth %d) %" PRIxGRUB_UINT64_T
" %x %" PRIxGRUB_UINT64_T "\n", depth,
node.key.object_id, node.key.type, node.key.offset);
node.key.object_id, node.key.type,
node.key.offset);
if (key_cmp (&node.key, key_in) == 0)
{
err = GRUB_ERR_NONE;
@ -433,7 +453,7 @@ lower_bound (struct grub_btrfs_data *data,
err = GRUB_ERR_NONE;
if (desc)
err = save_ref (desc, addr - sizeof (head), i - 1,
grub_le_to_cpu32 (head.nitems), 0);
grub_le_to_cpu32 (head.nitems), 0);
if (err)
return err;
addr = grub_le_to_cpu64 (node_last.addr);
@ -457,7 +477,7 @@ lower_bound (struct grub_btrfs_data *data,
&leaf, sizeof (leaf));
if (err)
return err;
grub_dprintf ("btrfs",
"leaf (depth %d) %" PRIxGRUB_UINT64_T
" %x %" PRIxGRUB_UINT64_T "\n", depth,
@ -465,31 +485,31 @@ lower_bound (struct grub_btrfs_data *data,
if (key_cmp (&leaf.key, key_in) == 0)
{
grub_memcpy (key_out, &leaf.key, sizeof(*key_out));
grub_memcpy (key_out, &leaf.key, sizeof (*key_out));
*outsize = grub_le_to_cpu32 (leaf.size);
*outaddr = addr + grub_le_to_cpu32 (leaf.offset);
if (desc)
return save_ref (desc, addr - sizeof (head), i,
grub_le_to_cpu32 (head.nitems), 1);
return GRUB_ERR_NONE;
return GRUB_ERR_NONE;
}
if (key_cmp (&leaf.key, key_in) > 0)
break;
have_last = 1;
leaf_last = leaf;
}
if (have_last)
{
grub_memcpy (key_out, &leaf_last.key, sizeof(*key_out));
grub_memcpy (key_out, &leaf_last.key, sizeof (*key_out));
*outsize = grub_le_to_cpu32 (leaf_last.size);
*outaddr = addr + grub_le_to_cpu32 (leaf_last.offset);
if (desc)
return save_ref (desc, addr - sizeof (head), i - 1,
grub_le_to_cpu32 (head.nitems), 1);
return GRUB_ERR_NONE;
return GRUB_ERR_NONE;
}
*outsize = 0;
*outaddr = 0;
@ -503,8 +523,7 @@ lower_bound (struct grub_btrfs_data *data,
}
static grub_device_t
find_device (struct grub_btrfs_data *data, grub_uint64_t id,
int do_rescan)
find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
{
grub_device_t dev_found = NULL;
auto int hook (const char *name);
@ -540,7 +559,7 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id,
grub_device_close (dev);
return 0;
}
dev_found = dev;
return 1;
}
@ -579,17 +598,16 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id,
}
static grub_err_t
grub_btrfs_read_logical (struct grub_btrfs_data *data,
grub_disk_addr_t addr,
grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
void *buf, grub_size_t size)
{
while (size > 0)
{
grub_uint8_t *ptr;
struct grub_btrfs_key *key;
struct grub_btrfs_chunk_item *chunk;
struct grub_btrfs_chunk_item *chunk;
grub_uint64_t csize;
grub_err_t err = 0;
grub_err_t err = 0;
struct grub_btrfs_key key_out;
int challoc = 0;
grub_device_t dev;
@ -601,15 +619,15 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
addr);
for (ptr = data->sblock.bootstrap_mapping;
ptr < data->sblock.bootstrap_mapping
+ sizeof (data->sblock.bootstrap_mapping)
- sizeof (struct grub_btrfs_key);
)
+ sizeof (data->sblock.bootstrap_mapping)
- sizeof (struct grub_btrfs_key);)
{
key = (struct grub_btrfs_key *) ptr;
if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK)
break;
chunk = (struct grub_btrfs_chunk_item *) (key + 1);
grub_dprintf ("btrfs", "%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n",
grub_dprintf ("btrfs",
"%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n",
grub_le_to_cpu64 (key->offset),
grub_le_to_cpu64 (chunk->size));
if (grub_le_to_cpu64 (key->offset) <= addr
@ -704,11 +722,11 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
middle = grub_divmod64 (off,
grub_le_to_cpu64 (chunk->stripe_length),
&low);
high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes),
&stripen);
stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
* high;
stripe_offset =
low + grub_le_to_cpu64 (chunk->stripe_length) * high;
csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
break;
}
@ -719,14 +737,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
middle = grub_divmod64 (off,
grub_le_to_cpu64 (chunk->stripe_length),
&low);
high = grub_divmod64 (middle,
grub_le_to_cpu16 (chunk->nsubstripes),
grub_le_to_cpu16 (chunk->nstripes)
/ grub_le_to_cpu16 (chunk->nsubstripes),
&stripen);
stripen *= grub_le_to_cpu16 (chunk->nstripes)
/ grub_le_to_cpu16 (chunk->nsubstripes);
redundancy = grub_le_to_cpu16 (chunk->nstripes)
/ grub_le_to_cpu16 (chunk->nsubstripes);
stripen *= grub_le_to_cpu16 (chunk->nsubstripes);
redundancy = grub_le_to_cpu16 (chunk->nsubstripes);
stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
* high;
csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
@ -759,7 +776,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
paddr = stripe->offset + stripe_offset;
grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
"+0x%" PRIxGRUB_UINT64_T " (%d stripes (%d substripes) of %"
"+0x%" PRIxGRUB_UINT64_T
" (%d stripes (%d substripes) of %"
PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T
" maps to 0x%" PRIxGRUB_UINT64_T "\n",
grub_le_to_cpu64 (key->offset),
@ -769,7 +787,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
grub_le_to_cpu64 (chunk->stripe_length),
stripen, stripe->offset);
grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T
" for laddr 0x%" PRIxGRUB_UINT64_T"\n", paddr,
" for laddr 0x%" PRIxGRUB_UINT64_T "\n", paddr,
addr);
dev = find_device (data, stripe->device_id, j);
@ -815,7 +833,7 @@ grub_btrfs_mount (grub_device_t dev)
}
data = grub_zalloc (sizeof (*data));
if (! data)
if (!data)
return NULL;
err = read_sblock (dev->disk, &data->sblock);
@ -866,8 +884,7 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data,
key_in.type = GRUB_BTRFS_ITEM_TYPE_INODE_ITEM;
key_in.offset = 0;
err = lower_bound (data, &key_in, &key_out, tree,
&elemaddr, &elemsize, NULL);
err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, NULL);
if (err)
return err;
if (num != key_out.object_id
@ -877,6 +894,80 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data,
return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode));
}
static grub_ssize_t
grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off,
char *obuf, grub_size_t osize)
{
grub_uint32_t total_size, cblock_size, ret = 0;
unsigned char buf[GRUB_BTRFS_LZO_BLOCK_SIZE];
total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
ibuf += sizeof (total_size);
if (isize < total_size)
return -1;
/* Jump forward to first block with requested data. */
while (off >= GRUB_BTRFS_LZO_BLOCK_SIZE)
{
cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
ibuf += sizeof (cblock_size);
if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE)
return -1;
off -= GRUB_BTRFS_LZO_BLOCK_SIZE;
ibuf += cblock_size;
}
while (osize > 0)
{
lzo_uint usize = GRUB_BTRFS_LZO_BLOCK_SIZE;
cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
ibuf += sizeof (cblock_size);
if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE)
return -1;
/* Block partially filled with requested data. */
if (off > 0 || osize < GRUB_BTRFS_LZO_BLOCK_SIZE)
{
grub_size_t to_copy = GRUB_BTRFS_LZO_BLOCK_SIZE - off;
if (to_copy > osize)
to_copy = osize;
if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize,
NULL) != LZO_E_OK)
return -1;
if (to_copy > usize)
to_copy = usize;
grub_memcpy(obuf, buf + off, to_copy);
osize -= to_copy;
ret += to_copy;
obuf += to_copy;
ibuf += cblock_size;
off = 0;
continue;
}
/* Decompress whole block directly to output buffer. */
if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, (lzo_bytep)obuf,
&usize, NULL) != LZO_E_OK)
return -1;
osize -= usize;
ret += usize;
obuf += usize;
ibuf += cblock_size;
}
return ret;
}
static grub_ssize_t
grub_btrfs_extent_read (struct grub_btrfs_data *data,
grub_uint64_t ino, grub_uint64_t tree,
@ -909,6 +1000,12 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
grub_error (GRUB_ERR_BAD_FS, "extent not found");
return -1;
}
if ((grub_ssize_t) elemsize < ((char *) &data->extent->inl
- (char *) data->extent))
{
grub_error (GRUB_ERR_BAD_FS, "extent descriptor is too short");
return -1;
}
data->extstart = grub_le_to_cpu64 (key_out.offset);
data->extsize = elemsize;
data->extent = grub_malloc (elemsize);
@ -917,26 +1014,22 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
if (!data->extent)
return grub_errno;
err = grub_btrfs_read_logical (data, elemaddr,
data->extent, elemsize);
err = grub_btrfs_read_logical (data, elemaddr, data->extent,
elemsize);
if (err)
return err;
data->extend = data->extstart
+ grub_le_to_cpu64 (data->extent->size);
data->extend = data->extstart + grub_le_to_cpu64 (data->extent->size);
if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR
&& (char *) &data->extent + elemsize
>= (char *) &data->extent->filled
+ sizeof (data->extent->filled))
data->extend = data->extstart
+ grub_le_to_cpu64 (data->extent->filled);
>= (char *) &data->extent->filled + sizeof (data->extent->filled))
data->extend =
data->extstart + grub_le_to_cpu64 (data->extent->filled);
grub_dprintf ("btrfs", "extent 0x%" PRIxGRUB_UINT64_T "+0x%"
PRIxGRUB_UINT64_T " (0x%"
PRIxGRUB_UINT64_T ")\n",
grub_dprintf ("btrfs", "regular extent 0x%" PRIxGRUB_UINT64_T "+0x%"
PRIxGRUB_UINT64_T "\n",
grub_le_to_cpu64 (key_out.offset),
grub_le_to_cpu64 (data->extent->size),
grub_le_to_cpu64 (data->extent->filled));
grub_le_to_cpu64 (data->extent->size));
if (data->extend <= pos)
{
grub_error (GRUB_ERR_BAD_FS, "extent not found");
@ -956,7 +1049,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
}
if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB)
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_LZO)
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"compression type 0x%x not supported",
@ -966,8 +1060,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
if (data->extent->encoding)
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"encoding not supported");
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "encoding not supported");
return -1;
}
@ -983,6 +1076,15 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
!= (grub_ssize_t) csize)
return -1;
}
else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
{
if (grub_btrfs_lzo_decompress(data->extent->inl, data->extsize -
((grub_uint8_t *) data->extent->inl
- (grub_uint8_t *) data->extent),
extoff, buf, csize)
!= (grub_ssize_t) csize)
return -1;
}
else
grub_memcpy (buf, data->extent->inl + extoff, csize);
break;
@ -992,10 +1094,13 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
grub_memset (buf, 0, csize);
break;
}
if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE)
{
char *tmp;
grub_uint64_t zsize;
grub_ssize_t ret;
zsize = grub_le_to_cpu64 (data->extent->compressed_size);
tmp = grub_malloc (zsize);
if (!tmp)
@ -1008,27 +1113,35 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
grub_free (tmp);
return -1;
}
if (grub_zlib_decompress (tmp, zsize, extoff
+ grub_le_to_cpu64 (data->extent->offset),
buf, csize) != (grub_ssize_t) csize)
{
grub_free (tmp);
return -1;
}
if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
ret = grub_zlib_decompress (tmp, zsize, extoff
+ grub_le_to_cpu64 (data->extent->offset),
buf, csize);
else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
ret = grub_btrfs_lzo_decompress (tmp, zsize, extoff
+ grub_le_to_cpu64 (data->extent->offset),
buf, csize);
else
ret = -1;
grub_free (tmp);
if (ret != (grub_ssize_t) csize)
return -1;
break;
}
err = grub_btrfs_read_logical (data,
grub_le_to_cpu64 (data->extent->laddr)
+ grub_le_to_cpu64 (data->extent->offset)
+ extoff,
buf, csize);
+ extoff, buf, csize);
if (err)
return -1;
break;
default:
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported extent type 0x%x", data->extent->type);
"unsupported extent type 0x%x", data->extent->type);
return -1;
}
buf += csize;
@ -1096,9 +1209,9 @@ find_path (struct grub_btrfs_data *data,
key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
key->offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen));
err = lower_bound (data, key, &key_out, *tree,
&elemaddr, &elemsize, NULL);
err = lower_bound (data, key, &key_out, *tree, &elemaddr, &elemsize,
NULL);
if (err)
{
grub_free (direl);
@ -1140,7 +1253,7 @@ find_path (struct grub_btrfs_data *data,
for (cdirel = direl;
(grub_uint8_t *) cdirel - (grub_uint8_t *) direl
< (grub_ssize_t) elemsize;
< (grub_ssize_t) elemsize;
cdirel = (void *) ((grub_uint8_t *) (direl + 1)
+ grub_le_to_cpu16 (cdirel->n)
+ grub_le_to_cpu16 (cdirel->m)))
@ -1174,7 +1287,7 @@ find_path (struct grub_btrfs_data *data,
return grub_error (GRUB_ERR_SYMLINK_LOOP,
"too deep nesting of symlinks");
}
err = grub_btrfs_read_inode (data, &inode,
cdirel->key.object_id, *tree);
if (err)
@ -1205,10 +1318,9 @@ find_path (struct grub_btrfs_data *data,
grub_free (tmp);
return grub_errno;
}
grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path,
grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path,
grub_strlen (path) + 1);
grub_free (path_alloc);
grub_free (origpath);
path = path_alloc = tmp;
if (path[0] == '/')
{
@ -1247,8 +1359,7 @@ find_path (struct grub_btrfs_data *data,
grub_free (origpath);
return err;
}
err = grub_btrfs_read_logical (data, elemaddr,
&ri, sizeof (ri));
err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri));
if (err)
{
grub_free (direl);
@ -1279,19 +1390,21 @@ find_path (struct grub_btrfs_data *data,
grub_free (path_alloc);
grub_free (origpath);
grub_free (direl);
return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x",
return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x",
cdirel->key.type);
}
}
grub_free (direl);
grub_free (origpath);
grub_free (path_alloc);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_btrfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_btrfs_data *data = grub_btrfs_mount (device);
struct grub_btrfs_key key_in, key_out;
@ -1310,23 +1423,28 @@ grub_btrfs_dir (grub_device_t device, const char *path,
err = find_path (data, path, &key_in, &tree, &type);
if (err)
return err;
{
grub_btrfs_unmount (data);
return err;
}
if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
{
grub_btrfs_unmount (data);
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
}
err = lower_bound (data, &key_in, &key_out, tree,
&elemaddr, &elemsize, &desc);
err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, &desc);
if (err)
return err;
{
grub_btrfs_unmount (data);
return err;
}
if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM
|| key_out.object_id != key_in.object_id)
{
r = next (data, &desc, &elemaddr, &elemsize, &key_out);
if (r <= 0)
{
free_iterator (&desc);
return -r;
}
goto out;
}
do
{
@ -1344,18 +1462,21 @@ grub_btrfs_dir (grub_device_t device, const char *path,
direl = grub_malloc (allocated + 1);
if (!direl)
{
free_iterator (&desc);
return grub_errno;
r = -grub_errno;
break;
}
}
err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize);
if (err)
return err;
{
r = -err;
break;
}
for (cdirel = direl;
(grub_uint8_t *) cdirel - (grub_uint8_t *) direl
< (grub_ssize_t) elemsize;
< (grub_ssize_t) elemsize;
cdirel = (void *) ((grub_uint8_t *) (direl + 1)
+ grub_le_to_cpu16 (cdirel->n)
+ grub_le_to_cpu16 (cdirel->m)))
@ -1384,7 +1505,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
}
while (r > 0);
out:
out:
grub_free (direl);
free_iterator (&desc);
@ -1456,7 +1577,7 @@ grub_btrfs_uuid (grub_device_t device, char **uuid)
*uuid = NULL;
data = grub_btrfs_mount (device);
if (! data)
if (!data)
return grub_errno;
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
@ -1482,7 +1603,7 @@ grub_btrfs_label (grub_device_t device, char **label)
*label = NULL;
data = grub_btrfs_mount (device);
if (! data)
if (!data)
return grub_errno;
*label = grub_strndup (data->sblock.label, sizeof (data->sblock.label));
@ -1492,26 +1613,55 @@ grub_btrfs_label (grub_device_t device, char **label)
return grub_errno;
}
static struct grub_fs grub_btrfs_fs =
{
.name = "btrfs",
.dir = grub_btrfs_dir,
.open = grub_btrfs_open,
.read = grub_btrfs_read,
.close = grub_btrfs_close,
.uuid = grub_btrfs_uuid,
.label = grub_btrfs_label,
#ifdef GRUB_UTIL
.reserved_first_sector = 1,
#endif
};
static grub_err_t
grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
unsigned int *nsectors,
grub_embed_type_t embed_type,
grub_disk_addr_t **sectors)
{
unsigned i;
GRUB_MOD_INIT(btrfs)
if (embed_type != GRUB_EMBED_PCBIOS)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"BtrFS currently supports only PC-BIOS embedding");
if (64 * 2 - 1 < *nsectors)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"Your core.img is unusually large. "
"It won't fit in the embedding area.");
*nsectors = 64 * 2 - 1;
*sectors = grub_malloc (*nsectors * sizeof (**sectors));
if (!*sectors)
return grub_errno;
for (i = 0; i < *nsectors; i++)
(*sectors)[i] = i + 1;
return GRUB_ERR_NONE;
}
#endif
static struct grub_fs grub_btrfs_fs = {
.name = "btrfs",
.dir = grub_btrfs_dir,
.open = grub_btrfs_open,
.read = grub_btrfs_read,
.close = grub_btrfs_close,
.uuid = grub_btrfs_uuid,
.label = grub_btrfs_label,
#ifdef GRUB_UTIL
.embed = grub_btrfs_embed,
.reserved_first_sector = 1,
#endif
};
GRUB_MOD_INIT (btrfs)
{
grub_fs_register (&grub_btrfs_fs);
}
GRUB_MOD_FINI(btrfs)
GRUB_MOD_FINI (btrfs)
{
grub_fs_unregister (&grub_btrfs_fs);
}

View file

@ -25,28 +25,74 @@
GRUB_MOD_LICENSE ("GPLv3+");
#ifndef MODE_USTAR
/* cpio support */
#define MAGIC_BCPIO 070707
#define ATTR_TYPE 0160000
#define ATTR_FILE 0100000
#define ATTR_DIR 0040000
#define ATTR_LNK 0120000
#ifdef MODE_ODC
#define ALIGN_CPIO(x) x
#define MAGIC "070707"
struct head
{
grub_uint16_t magic;
char magic[6];
char dev[6];
char ino[6];
char mode[6];
char uid[6];
char gid[6];
char nlink[6];
char rdev[6];
char mtime[11];
char namesize[6];
char filesize[11];
} __attribute__ ((packed));
#elif defined (MODE_NEWC)
#define ALIGN_CPIO(x) (ALIGN_UP ((x), 4))
#define MAGIC "070701"
#define MAGIC2 "070702"
struct head
{
char magic[6];
char ino[8];
char mode[8];
char uid[8];
char gid[8];
char nlink[8];
char mtime[8];
char filesize[8];
char devmajor[8];
char devminor[8];
char rdevmajor[8];
char rdevminor[8];
char namesize[8];
char check[8];
} __attribute__ ((packed));
#elif !defined (MODE_USTAR)
/* cpio support */
#define ALIGN_CPIO(x) (ALIGN_UP ((x), 2))
#ifdef MODE_BIGENDIAN
#define MAGIC "\x71\xc7"
#else
#define MAGIC "\xc7\x71"
#endif
struct head
{
grub_uint16_t magic[1];
grub_uint16_t dev;
grub_uint16_t ino;
grub_uint16_t mode;
grub_uint16_t mode[1];
grub_uint16_t uid;
grub_uint16_t gid;
grub_uint16_t nlink;
grub_uint16_t rdev;
grub_uint16_t mtime_1;
grub_uint16_t mtime_2;
grub_uint16_t namesize;
grub_uint16_t filesize_1;
grub_uint16_t filesize_2;
grub_uint16_t mtime[2];
grub_uint16_t namesize[1];
grub_uint16_t filesize[2];
} __attribute__ ((packed));
#else
/* tar support */
#define MAGIC_USTAR "ustar"
#define MAGIC "ustar"
struct head
{
char name[100];
@ -71,60 +117,140 @@ struct head
struct grub_cpio_data
{
grub_disk_t disk;
grub_uint32_t hofs;
grub_uint32_t dofs;
grub_uint32_t size;
grub_off_t hofs;
grub_off_t dofs;
grub_off_t size;
#ifdef MODE_USTAR
char *linkname;
grub_size_t linkname_alloc;
#endif
};
static grub_dl_t my_mod;
static inline void
canonicalize (char *name)
{
char *iptr, *optr;
for (iptr = name, optr = name; *iptr; )
{
while (*iptr == '/')
iptr++;
if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0))
{
iptr += 2;
continue;
}
while (*iptr && *iptr != '/')
*optr++ = *iptr++;
if (*iptr)
*optr++ = *iptr++;
}
*optr = 0;
}
#if defined (MODE_ODC) || defined (MODE_USTAR)
static inline unsigned long long
read_number (const char *str, grub_size_t size)
{
unsigned long long ret = 0;
while (size-- && *str >= '0' && *str <= '7')
ret = (ret << 3) | (*str++ & 0xf);
return ret;
}
#elif defined (MODE_NEWC)
static inline unsigned long long
read_number (const char *str, grub_size_t size)
{
unsigned long long ret = 0;
while (size-- && grub_isxdigit (*str))
{
char dig = *str++;
if (dig >= '0' && dig <= '9')
dig &= 0xf;
else if (dig >= 'a' && dig <= 'f')
dig -= 'a' - 10;
else
dig -= 'A' - 10;
ret = (ret << 4) | (dig);
}
return ret;
}
#else
static inline unsigned long long
read_number (const grub_uint16_t *arr, grub_size_t size)
{
long long ret = 0;
#ifdef MODE_BIGENDIAN
while (size--)
ret = (ret << 16) | grub_be_to_cpu16 (*arr++);
#else
while (size--)
ret = (ret << 16) | grub_le_to_cpu16 (*arr++);
#endif
return ret;
}
#endif
static grub_err_t
grub_cpio_find_file (struct grub_cpio_data *data, char **name,
grub_int32_t *mtime, grub_uint32_t * ofs)
grub_int32_t *mtime, grub_disk_addr_t *ofs,
grub_uint32_t *mode)
{
#ifndef MODE_USTAR
struct head hd;
struct head hd;
grub_size_t namesize;
grub_uint32_t modeval;
if (grub_disk_read
(data->disk, 0, data->hofs, sizeof (hd), &hd))
return grub_errno;
if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
return grub_errno;
if (hd.magic != MAGIC_BCPIO)
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0
#ifdef MAGIC2
&& grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0
#endif
)
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize));
if (mtime)
*mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime));
modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode));
namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize));
data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2;
if (mtime)
*mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2;
if (mode)
*mode = modeval;
if (hd.namesize & 1)
hd.namesize++;
*name = grub_malloc (namesize + 1);
if (*name == NULL)
return grub_errno;
if ((*name = grub_malloc (hd.namesize)) == NULL)
return grub_errno;
if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
namesize, *name))
{
grub_free (*name);
return grub_errno;
}
(*name)[namesize] = 0;
if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
hd.namesize, *name))
{
grub_free (*name);
return grub_errno;
}
if (data->size == 0 && modeval == 0 && namesize == 11
&& grub_memcmp(*name, "TRAILER!!!", 11) == 0)
{
*ofs = 0;
grub_free (*name);
return GRUB_ERR_NONE;
}
if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1
&& ! grub_memcmp(*name, "TRAILER!!!", 11))
{
*ofs = 0;
return GRUB_ERR_NONE;
}
canonicalize (*name);
data->dofs = data->hofs + sizeof (hd) + hd.namesize;
*ofs = data->dofs + data->size;
if (data->size & 1)
(*ofs)++;
data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize);
*ofs = data->dofs + ALIGN_CPIO (data->size);
#else
struct head hd;
struct head hd;
int reread = 0, have_longname = 0, have_longlink = 0;
if (grub_disk_read
(data->disk, 0, data->hofs, sizeof (hd), &hd))
for (reread = 0; reread < 3; reread++)
{
if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
return grub_errno;
if (!hd.name[0])
@ -133,18 +259,105 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name,
return GRUB_ERR_NONE;
}
if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1))
if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1))
return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");
if ((*name = grub_strdup (hd.name)) == NULL)
return grub_errno;
if (hd.typeflag == 'L')
{
grub_err_t err;
grub_size_t namesize = read_number (hd.size, sizeof (hd.size));
*name = grub_malloc (namesize + 1);
if (*name == NULL)
return grub_errno;
err = grub_disk_read (data->disk, 0,
data->hofs + GRUB_DISK_SECTOR_SIZE, namesize,
*name);
(*name)[namesize] = 0;
if (err)
return err;
data->hofs += GRUB_DISK_SECTOR_SIZE
+ ((namesize + GRUB_DISK_SECTOR_SIZE - 1) &
~(GRUB_DISK_SECTOR_SIZE - 1));
have_longname = 1;
continue;
}
data->size = grub_strtoul (hd.size, NULL, 8);
if (hd.typeflag == 'K')
{
grub_err_t err;
grub_size_t linksize = read_number (hd.size, sizeof (hd.size));
if (data->linkname_alloc < linksize + 1)
{
char *n;
n = grub_malloc (2 * (linksize + 1));
if (!n)
return grub_errno;
grub_free (data->linkname);
data->linkname = n;
data->linkname_alloc = 2 * (linksize + 1);
}
err = grub_disk_read (data->disk, 0,
data->hofs + GRUB_DISK_SECTOR_SIZE, linksize,
data->linkname);
if (err)
return err;
data->linkname[linksize] = 0;
data->hofs += GRUB_DISK_SECTOR_SIZE
+ ((linksize + GRUB_DISK_SECTOR_SIZE - 1) &
~(GRUB_DISK_SECTOR_SIZE - 1));
have_longlink = 1;
continue;
}
if (!have_longname)
{
*name = grub_strndup (hd.name, sizeof (hd.name));
if (*name == NULL)
return grub_errno;
}
data->size = read_number (hd.size, sizeof (hd.size));
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
*ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
~(GRUB_DISK_SECTOR_SIZE - 1));
if (mtime)
*mtime = grub_strtoul (hd.mtime, NULL, 8);
*mtime = read_number (hd.mtime, sizeof (hd.mtime));
if (mode)
{
*mode = read_number (hd.mode, sizeof (hd.mode));
switch (hd.typeflag)
{
case '2':
*mode |= ATTR_LNK;
break;
case '0':
*mode |= ATTR_FILE;
break;
case '5':
*mode |= ATTR_DIR;
break;
}
}
if (!have_longlink)
{
if (data->linkname_alloc < 101)
{
char *n;
n = grub_malloc (101);
if (!n)
return grub_errno;
grub_free (data->linkname);
data->linkname = n;
data->linkname_alloc = 101;
}
grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname));
data->linkname[100] = 0;
}
canonicalize (*name);
return GRUB_ERR_NONE;
}
#endif
return GRUB_ERR_NONE;
}
@ -158,15 +371,14 @@ grub_cpio_mount (grub_disk_t disk)
if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd))
goto fail;
#ifndef MODE_USTAR
if (hd.magic != MAGIC_BCPIO)
#else
if (grub_memcmp (hd.magic, MAGIC_USTAR,
sizeof (MAGIC_USTAR) - 1))
if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)
#ifdef MAGIC2
&& grub_memcmp (hd.magic, MAGIC2, sizeof (MAGIC2) - 1)
#endif
)
goto fail;
data = (struct grub_cpio_data *) grub_malloc (sizeof (*data));
data = (struct grub_cpio_data *) grub_zalloc (sizeof (*data));
if (!data)
goto fail;
@ -186,15 +398,107 @@ fail:
}
static grub_err_t
grub_cpio_dir (grub_device_t device, const char *path,
handle_symlink (struct grub_cpio_data *data,
const char *fn, char **name,
grub_uint32_t mode, int *restart)
{
grub_size_t flen;
char *target;
#ifndef MODE_USTAR
grub_err_t err;
#endif
char *ptr;
char *lastslash;
grub_size_t prefixlen;
char *rest;
grub_size_t size;
*restart = 0;
if ((mode & ATTR_TYPE) != ATTR_LNK)
return GRUB_ERR_NONE;
flen = grub_strlen (fn);
if (grub_memcmp (*name, fn, flen) != 0
|| ((*name)[flen] != 0 && (*name)[flen] != '/'))
return GRUB_ERR_NONE;
rest = *name + flen;
lastslash = rest;
if (*rest)
rest++;
while (lastslash >= *name && *lastslash != '/')
lastslash--;
if (lastslash >= *name)
prefixlen = lastslash - *name;
else
prefixlen = 0;
if (prefixlen)
prefixlen++;
#ifdef MODE_USTAR
size = grub_strlen (data->linkname);
#else
size = data->size;
#endif
if (size == 0)
return GRUB_ERR_NONE;
target = grub_malloc (size + grub_strlen (*name) + 2);
if (!target)
return grub_errno;
#ifdef MODE_USTAR
grub_memcpy (target + prefixlen, data->linkname, size);
#else
err = grub_disk_read (data->disk, 0, data->dofs, data->size,
target + prefixlen);
if (err)
return err;
#endif
if (target[prefixlen] == '/')
{
grub_memmove (target, target + prefixlen, data->size - 1);
ptr = target + data->size - 1;
ptr = grub_stpcpy (ptr, rest);
*ptr = 0;
grub_dprintf ("cpio", "symlink redirected %s to %s\n",
*name, target);
grub_free (*name);
*name = target;
*restart = 1;
return GRUB_ERR_NONE;
}
if (prefixlen)
{
grub_memcpy (target, *name, prefixlen);
target[prefixlen-1] = '/';
}
ptr = target + prefixlen + size;
ptr = grub_stpcpy (ptr, rest);
*ptr = 0;
grub_dprintf ("cpio", "symlink redirected %s to %s\n",
*name, target);
grub_free (*name);
*name = target;
*restart = 1;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cpio_dir (grub_device_t device, const char *path_in,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_cpio_data *data;
grub_uint32_t ofs;
char *prev, *name;
const char *np;
int len;
grub_disk_addr_t ofs;
char *prev, *name, *path, *ptr;
grub_size_t len;
int symlinknest = 0;
path = grub_strdup (path_in + 1);
if (!path)
return grub_errno;
for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--)
*ptr = 0;
grub_dl_ref (my_mod);
@ -202,35 +506,39 @@ grub_cpio_dir (grub_device_t device, const char *path,
data = grub_cpio_mount (device->disk);
if (!data)
goto fail;
np = path + 1;
len = grub_strlen (path) - 1;
{
grub_free (path);
return grub_errno;
}
len = grub_strlen (path);
data->hofs = 0;
while (1)
{
grub_int32_t mtime;
grub_uint32_t mode;
grub_err_t err;
if (grub_cpio_find_file (data, &name, &mtime, &ofs))
if (grub_cpio_find_file (data, &name, &mtime, &ofs, &mode))
goto fail;
if (!ofs)
break;
if (grub_memcmp (np, name, len) == 0)
if (grub_memcmp (path, name, len) == 0
&& (name[len] == 0 || name[len] == '/' || len == 0))
{
char *p, *n;
n = name + len;
if (*n == '/')
while (*n == '/')
n++;
p = grub_strchr (name + len, '/');
p = grub_strchr (n, '/');
if (p)
*p = 0;
if ((!prev) || (grub_strcmp (prev, name) != 0))
if (((!prev) || (grub_strcmp (prev, n) != 0)) && *n != 0)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
@ -238,19 +546,43 @@ grub_cpio_dir (grub_device_t device, const char *path,
info.mtime = mtime;
info.mtimeset = 1;
hook (name + len, &info);
if (hook (n, &info))
goto fail;
grub_free (prev);
prev = name;
}
else
grub_free (name);
{
int restart;
err = handle_symlink (data, name, &path, mode, &restart);
grub_free (name);
if (err)
goto fail;
if (restart)
{
len = grub_strlen (path);
if (++symlinknest == 8)
{
grub_error (GRUB_ERR_SYMLINK_LOOP,
"too deep nesting of symlinks");
goto fail;
}
ofs = 0;
}
}
}
else
grub_free (name);
data->hofs = ofs;
}
fail:
grub_free (path);
grub_free (prev);
#ifdef MODE_USTAR
grub_free (data->linkname);
#endif
grub_free (data);
grub_dl_unref (my_mod);
@ -259,23 +591,33 @@ fail:
}
static grub_err_t
grub_cpio_open (grub_file_t file, const char *name)
grub_cpio_open (grub_file_t file, const char *name_in)
{
struct grub_cpio_data *data;
grub_uint32_t ofs;
grub_disk_addr_t ofs;
char *fn;
int i, j;
char *name = grub_strdup (name_in + 1);
int symlinknest = 0;
if (!name)
return grub_errno;
grub_dl_ref (my_mod);
data = grub_cpio_mount (file->device->disk);
if (!data)
goto fail;
{
grub_free (name);
return grub_errno;
}
data->hofs = 0;
while (1)
{
if (grub_cpio_find_file (data, &fn, NULL, &ofs))
grub_uint32_t mode;
int restart;
if (grub_cpio_find_file (data, &fn, NULL, &ofs, &mode))
goto fail;
if (!ofs)
@ -284,33 +626,31 @@ grub_cpio_open (grub_file_t file, const char *name)
break;
}
/* Compare NAME and FN by hand in order to cope with duplicate
slashes. */
i = 0;
j = 0;
while (name[i] == '/')
i++;
while (1)
if (handle_symlink (data, fn, &name, mode, &restart))
{
if (name[i] != fn[j])
goto no_match;
if (name[i] == '\0')
break;
while (name[i] == '/' && name[i+1] == '/')
i++;
i++;
j++;
grub_free (fn);
goto fail;
}
if (name[i] != fn[j])
if (restart)
{
ofs = 0;
if (++symlinknest == 8)
{
grub_error (GRUB_ERR_SYMLINK_LOOP,
"too deep nesting of symlinks");
goto fail;
}
goto no_match;
}
if (grub_strcmp (name, fn) != 0)
goto no_match;
file->data = data;
file->size = data->size;
grub_free (fn);
grub_free (name);
return GRUB_ERR_NONE;
@ -321,8 +661,11 @@ grub_cpio_open (grub_file_t file, const char *name)
}
fail:
#ifdef MODE_USTAR
grub_free (data->linkname);
#endif
grub_free (data);
grub_free (name);
grub_dl_unref (my_mod);
@ -342,7 +685,13 @@ grub_cpio_read (grub_file_t file, char *buf, grub_size_t len)
static grub_err_t
grub_cpio_close (grub_file_t file)
{
grub_free (file->data);
struct grub_cpio_data *data;
data = file->data;
#ifdef MODE_USTAR
grub_free (data->linkname);
#endif
grub_free (data);
grub_dl_unref (my_mod);
@ -352,6 +701,10 @@ grub_cpio_close (grub_file_t file)
static struct grub_fs grub_cpio_fs = {
#ifdef MODE_USTAR
.name = "tarfs",
#elif defined (MODE_ODC)
.name = "odc",
#elif defined (MODE_NEWC)
.name = "newc",
#else
.name = "cpiofs",
#endif
@ -366,6 +719,12 @@ static struct grub_fs grub_cpio_fs = {
#ifdef MODE_USTAR
GRUB_MOD_INIT (tar)
#elif defined (MODE_ODC)
GRUB_MOD_INIT (odc)
#elif defined (MODE_NEWC)
GRUB_MOD_INIT (newc)
#elif defined (MODE_BIGENDIAN)
GRUB_MOD_INIT (cpio_be)
#else
GRUB_MOD_INIT (cpio)
#endif
@ -376,6 +735,12 @@ GRUB_MOD_INIT (cpio)
#ifdef MODE_USTAR
GRUB_MOD_FINI (tar)
#elif defined (MODE_ODC)
GRUB_MOD_FINI (odc)
#elif defined (MODE_NEWC)
GRUB_MOD_FINI (newc)
#elif defined (MODE_BIGENDIAN)
GRUB_MOD_FINI (cpio_be)
#else
GRUB_MOD_FINI (cpio)
#endif

View file

@ -1,2 +1,2 @@
#define MODE_BIGENDIAN 1
#include "afs.c"
#include "cpio.c"

2
grub-core/fs/exfat.c Normal file
View file

@ -0,0 +1,2 @@
#define MODE_EXFAT 1
#include "fat.c"

View file

@ -21,10 +21,6 @@
#define EXT2_MAGIC 0xEF53
/* Amount of indirect blocks in an inode. */
#define INDIRECT_BLOCKS 12
/* Maximum length of a pathname. */
#define EXT2_PATH_MAX 4096
/* Maximum nesting of symlinks, used to prevent a loop. */
#define EXT2_MAX_SYMLINKCNT 8
/* The good old revision and the default inode size. */
#define EXT2_GOOD_OLD_REVISION 0
@ -337,7 +333,7 @@ grub_ext2_blockgroup (struct grub_ext2_data *data, int group,
}
static struct grub_ext4_extent_header *
grub_ext4_find_leaf (struct grub_ext2_data *data, char *buf,
grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf,
struct grub_ext4_extent_header *ext_block,
grub_uint32_t fileblock)
{
@ -387,7 +383,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG)
{
char buf[EXT2_BLOCK_SIZE(data)];
GRUB_PROPERLY_ALIGNED_ARRAY (buf, EXT2_BLOCK_SIZE(data));
struct grub_ext4_extent_header *leaf;
struct grub_ext4_extent *ext;
int i;
@ -689,7 +685,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
if (dirent.direntlen == 0)
return 0;
if (dirent.namelen != 0)
if (dirent.inode != 0 && dirent.namelen != 0)
{
char filename[dirent.namelen + 1];
struct grub_fshelp_node *fdiro;
@ -896,7 +892,8 @@ grub_ext2_label (grub_device_t device, char **label)
data = grub_ext2_mount (disk);
if (data)
*label = grub_strndup (data->sblock.volume_name, 14);
*label = grub_strndup (data->sblock.volume_name,
sizeof (data->sblock.volume_name));
else
*label = NULL;

View file

@ -30,28 +30,116 @@
GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_FAT_DIR_ENTRY_SIZE 32
enum
{
GRUB_FAT_ATTR_READ_ONLY = 0x01,
GRUB_FAT_ATTR_HIDDEN = 0x02,
GRUB_FAT_ATTR_SYSTEM = 0x04,
#ifndef MODE_EXFAT
GRUB_FAT_ATTR_VOLUME_ID = 0x08,
#endif
GRUB_FAT_ATTR_DIRECTORY = 0x10,
GRUB_FAT_ATTR_ARCHIVE = 0x20,
#define GRUB_FAT_ATTR_READ_ONLY 0x01
#define GRUB_FAT_ATTR_HIDDEN 0x02
#define GRUB_FAT_ATTR_SYSTEM 0x04
#define GRUB_FAT_ATTR_VOLUME_ID 0x08
#define GRUB_FAT_ATTR_DIRECTORY 0x10
#define GRUB_FAT_ATTR_ARCHIVE 0x20
#ifndef MODE_EXFAT
GRUB_FAT_ATTR_LONG_NAME = (GRUB_FAT_ATTR_READ_ONLY
| GRUB_FAT_ATTR_HIDDEN
| GRUB_FAT_ATTR_SYSTEM
| GRUB_FAT_ATTR_VOLUME_ID),
#endif
GRUB_FAT_ATTR_VALID = (GRUB_FAT_ATTR_READ_ONLY
| GRUB_FAT_ATTR_HIDDEN
| GRUB_FAT_ATTR_SYSTEM
| GRUB_FAT_ATTR_DIRECTORY
| GRUB_FAT_ATTR_ARCHIVE
#ifndef MODE_EXFAT
| GRUB_FAT_ATTR_VOLUME_ID
#endif
)
};
#define GRUB_FAT_MAXFILE 256
#ifdef MODE_EXFAT
struct grub_exfat_bpb
{
grub_uint8_t jmp_boot[3];
grub_uint8_t oem_name[8];
grub_uint8_t mbz[53];
grub_uint64_t num_hidden_sectors;
grub_uint64_t num_total_sectors;
grub_uint32_t num_reserved_sectors;
grub_uint32_t sectors_per_fat;
grub_uint32_t cluster_offset;
grub_uint32_t cluster_count;
grub_uint32_t root_cluster;
grub_uint32_t num_serial;
grub_uint16_t fs_revision;
grub_uint16_t volume_flags;
grub_uint8_t bytes_per_sector_shift;
grub_uint8_t sectors_per_cluster_shift;
grub_uint8_t num_fats;
grub_uint8_t num_ph_drive;
grub_uint8_t reserved[8];
} __attribute__ ((packed));
typedef struct grub_exfat_bpb grub_current_fat_bpb_t;
#else
typedef struct grub_fat_bpb grub_current_fat_bpb_t;
#endif
#define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \
| GRUB_FAT_ATTR_HIDDEN \
| GRUB_FAT_ATTR_SYSTEM \
| GRUB_FAT_ATTR_VOLUME_ID)
#define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \
| GRUB_FAT_ATTR_HIDDEN \
| GRUB_FAT_ATTR_SYSTEM \
| GRUB_FAT_ATTR_DIRECTORY \
| GRUB_FAT_ATTR_ARCHIVE \
| GRUB_FAT_ATTR_VOLUME_ID)
#ifdef MODE_EXFAT
struct grub_fat_dir_entry
{
grub_uint8_t entry_type;
union
{
grub_uint8_t placeholder[31];
struct {
grub_uint8_t secondary_count;
grub_uint16_t checksum;
grub_uint16_t attr;
grub_uint16_t reserved1;
grub_uint32_t c_time;
grub_uint32_t m_time;
grub_uint32_t a_time;
grub_uint8_t c_time_tenth;
grub_uint8_t m_time_tenth;
grub_uint8_t a_time_tenth;
grub_uint8_t reserved2[9];
} __attribute__ ((packed)) file;
struct {
grub_uint8_t flags;
grub_uint8_t reserved1;
grub_uint8_t name_length;
grub_uint16_t name_hash;
grub_uint16_t reserved2;
grub_uint64_t valid_size;
grub_uint32_t reserved3;
grub_uint32_t first_cluster;
grub_uint64_t file_size;
} __attribute__ ((packed)) stream_extension;
struct {
grub_uint8_t flags;
grub_uint16_t str[15];
} __attribute__ ((packed)) file_name;
struct {
grub_uint8_t character_count;
grub_uint16_t str[15];
} __attribute__ ((packed)) volume_label;
} __attribute__ ((packed)) type_specific;
} __attribute__ ((packed));
struct grub_fat_dir_node
{
grub_uint32_t attr;
grub_uint32_t first_cluster;
grub_uint64_t file_size;
grub_uint64_t valid_size;
int have_stream;
int is_label;
};
typedef struct grub_fat_dir_node grub_fat_dir_node_t;
#else
struct grub_fat_dir_entry
{
grub_uint8_t name[11];
@ -80,6 +168,10 @@ struct grub_fat_long_name_entry
grub_uint16_t name3[2];
} __attribute__ ((packed));
typedef struct grub_fat_dir_entry grub_fat_dir_node_t;
#endif
struct grub_fat_data
{
int logical_sector_bits;
@ -90,8 +182,10 @@ struct grub_fat_data
int fat_size;
grub_uint32_t root_cluster;
#ifndef MODE_EXFAT
grub_uint32_t root_sector;
grub_uint32_t num_root_sectors;
#endif
int cluster_bits;
grub_uint32_t cluster_eof_mark;
@ -109,6 +203,7 @@ struct grub_fat_data
static grub_dl_t my_mod;
#ifndef MODE_EXFAT
static int
fat_log2 (unsigned x)
{
@ -125,11 +220,12 @@ fat_log2 (unsigned x)
return i;
}
#endif
static struct grub_fat_data *
grub_fat_mount (grub_disk_t disk)
{
struct grub_fat_bpb bpb;
grub_current_fat_bpb_t bpb;
struct grub_fat_data *data = 0;
grub_uint32_t first_fat, magic;
@ -144,20 +240,30 @@ grub_fat_mount (grub_disk_t disk)
if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb))
goto fail;
if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT12", 5)
&& grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT16", 5)
&& grub_strncmp((const char *) bpb.version_specific.fat32.fstype, "FAT32", 5))
goto fail;
#ifdef MODE_EXFAT
if (grub_memcmp ((const char *) bpb.oem_name, "EXFAT ",
sizeof (bpb.oem_name)) != 0)
goto fail;
#endif
/* Get the sizes of logical sectors and clusters. */
#ifdef MODE_EXFAT
data->logical_sector_bits = bpb.bytes_per_sector_shift;
#else
data->logical_sector_bits =
fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector));
if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS)
#endif
if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS
|| data->logical_sector_bits >= 16)
goto fail;
data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
#ifdef MODE_EXFAT
data->cluster_bits = bpb.sectors_per_cluster_shift;
#else
data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
if (data->cluster_bits < 0)
#endif
if (data->cluster_bits < 0 || data->cluster_bits > 25)
goto fail;
data->cluster_bits += data->logical_sector_bits;
@ -167,18 +273,28 @@ grub_fat_mount (grub_disk_t disk)
if (data->fat_sector == 0)
goto fail;
#ifdef MODE_EXFAT
data->sectors_per_fat = (grub_le_to_cpu32 (bpb.sectors_per_fat)
<< data->logical_sector_bits);
#else
data->sectors_per_fat = ((bpb.sectors_per_fat_16
? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
: grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32))
<< data->logical_sector_bits);
#endif
if (data->sectors_per_fat == 0)
goto fail;
/* Get the number of sectors in this volume. */
#ifdef MODE_EXFAT
data->num_sectors = ((grub_le_to_cpu64 (bpb.num_total_sectors))
<< data->logical_sector_bits);
#else
data->num_sectors = ((bpb.num_total_sectors_16
? grub_le_to_cpu16 (bpb.num_total_sectors_16)
: grub_le_to_cpu32 (bpb.num_total_sectors_32))
<< data->logical_sector_bits);
#endif
if (data->num_sectors == 0)
goto fail;
@ -186,22 +302,44 @@ grub_fat_mount (grub_disk_t disk)
if (bpb.num_fats == 0)
goto fail;
#ifndef MODE_EXFAT
data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
data->num_root_sectors
= ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries)
* GRUB_FAT_DIR_ENTRY_SIZE
* sizeof (struct grub_fat_dir_entry)
+ grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
>> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
<< (data->logical_sector_bits));
#endif
#ifdef MODE_EXFAT
data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset)
<< data->logical_sector_bits);
data->num_clusters = (grub_le_to_cpu32 (bpb.cluster_count)
<< data->logical_sector_bits);
#else
data->cluster_sector = data->root_sector + data->num_root_sectors;
data->num_clusters = (((data->num_sectors - data->cluster_sector)
>> (data->cluster_bits + data->logical_sector_bits))
+ 2);
#endif
if (data->num_clusters <= 2)
goto fail;
#ifdef MODE_EXFAT
{
/* exFAT. */
grub_uint16_t flags = grub_le_to_cpu16 (bpb.volume_flags);
data->root_cluster = grub_le_to_cpu32 (bpb.root_cluster);
data->fat_size = 32;
data->cluster_eof_mark = 0xffffffff;
if ((flags & 0x1) && bpb.num_fats > 1)
data->fat_sector += data->sectors_per_fat;
}
#else
if (! bpb.sectors_per_fat_16)
{
/* FAT32. */
@ -243,6 +381,7 @@ grub_fat_mount (grub_disk_t disk)
data->cluster_eof_mark = 0xfff8;
}
}
#endif
/* More sanity checks. */
if (data->num_sectors <= data->fat_sector)
@ -274,17 +413,25 @@ grub_fat_mount (grub_disk_t disk)
}
/* Serial number. */
#ifdef MODE_EXFAT
data->uuid = grub_le_to_cpu32 (bpb.num_serial);
#else
if (bpb.sectors_per_fat_16)
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
else
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
#endif
#ifndef MODE_EXFAT
/* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
descriptor, even if it is a so-called superfloppy (e.g. an USB key).
The check may be too strict for this kind of stupid BIOSes, as
they overwrite the media descriptor. */
if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
goto fail;
#else
(void) magic;
#endif
/* Start from the root directory. */
data->file_cluster = data->root_cluster;
@ -311,6 +458,7 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
grub_ssize_t ret = 0;
unsigned long sector;
#ifndef MODE_EXFAT
/* This is a special case. FAT12 and FAT16 doesn't have the root directory
in clusters. */
if (data->file_cluster == ~0U)
@ -324,13 +472,14 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
return size;
}
#endif
/* Calculate the logical cluster number and offset. */
logical_cluster_bits = (data->cluster_bits
+ data->logical_sector_bits
+ GRUB_DISK_SECTOR_BITS);
logical_cluster = offset >> logical_cluster_bits;
offset &= (1 << logical_cluster_bits) - 1;
offset &= (1ULL << logical_cluster_bits) - 1;
if (logical_cluster < data->cur_cluster_num)
{
@ -422,13 +571,116 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
return ret;
}
#ifdef MODE_EXFAT
static grub_err_t
grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
int (*hook) (const char *filename,
grub_fat_dir_node_t *node))
{
struct grub_fat_dir_entry dir;
grub_ssize_t offset = -sizeof(dir);
grub_uint16_t *unibuf;
char *filename;
unibuf = grub_malloc (15 * 256 * 2);
filename = grub_malloc (15 * 256 * GRUB_MAX_UTF8_PER_UTF16 + 1);
while (1)
{
offset += sizeof (dir);
if (grub_fat_read_data (disk, data, 0,
offset, sizeof (dir), (char *) &dir)
!= sizeof (dir))
break;
if (dir.entry_type == 0)
break;
if (!(dir.entry_type & 0x80))
continue;
if (dir.entry_type == 0x85)
{
unsigned i, nsec, slots = 0;
grub_fat_dir_node_t node;
nsec = dir.type_specific.file.secondary_count;
node.attr = grub_cpu_to_le32 (dir.type_specific.file.attr);
node.have_stream = 0;
for (i = 0; i < nsec; i++)
{
struct grub_fat_dir_entry sec;
offset += sizeof (sec);
if (grub_fat_read_data (disk, data, 0,
offset, sizeof (sec), (char *) &sec)
!= sizeof (sec))
break;
if (!(sec.entry_type & 0x80))
continue;
if (!(sec.entry_type & 0x40))
break;
switch (sec.entry_type)
{
case 0xc0:
node.first_cluster = grub_cpu_to_le32 (sec.type_specific.stream_extension.first_cluster);
node.valid_size
= grub_cpu_to_le64 (sec.type_specific.stream_extension.valid_size);
node.file_size
= grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size);
node.have_stream = 1;
break;
case 0xc1:
grub_memcpy (unibuf + slots * 15,
sec.type_specific.file_name.str, 30);
slots++;
break;
default:
grub_dprintf ("exfat", "unknown secondary type 0x%02x\n",
sec.entry_type);
}
}
if (i != nsec)
{
offset -= sizeof (dir);
continue;
}
*grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
slots * 15) = '\0';
if (hook (filename, &node))
break;
continue;
}
/* Allocation bitmap. */
if (dir.entry_type == 0x81)
continue;
/* Upcase table. */
if (dir.entry_type == 0x82)
continue;
/* Volume label. */
if (dir.entry_type == 0x83)
continue;
grub_dprintf ("exfat", "unknown primary type 0x%02x\n", dir.entry_type);
}
grub_free (filename);
grub_free (unibuf);
return grub_errno;
}
#else
static grub_err_t
grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
int (*hook) (const char *filename,
struct grub_fat_dir_entry *dir))
{
struct grub_fat_dir_entry dir;
char *filename, *filep = 0;
char *filename;
char *filep = 0;
grub_uint16_t *unibuf;
int slot = -1, slots = -1;
int checksum = -1;
@ -438,7 +690,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
/* Allocate space enough to hold a long name. */
filename = grub_malloc (0x40 * 13 * 4 + 1);
filename = grub_malloc (0x40 * 13 * GRUB_MAX_UTF8_PER_UTF16 + 1);
unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2);
if (! filename || ! unibuf)
{
@ -455,10 +707,11 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
offset += sizeof (dir);
/* Read a directory entry. */
if ((grub_fat_read_data (disk, data, 0,
if (grub_fat_read_data (disk, data, 0,
offset, sizeof (dir), (char *) &dir)
!= sizeof (dir) || dir.name[0] == 0))
!= sizeof (dir) || dir.name[0] == 0)
break;
/* Handle long name entries. */
if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
{
@ -543,7 +796,6 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
filep++;
}
*filep = '\0';
if (hook (filename, &dir))
break;
}
@ -553,7 +805,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
return grub_errno;
}
#endif
/* Find the underlying directory or file in PATH and return the
next path. If there is no next path or an error occurs, return NULL.
@ -569,8 +821,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
int call_hook;
int found = 0;
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
auto int iter_hook (const char *filename, grub_fat_dir_node_t *dir);
int iter_hook (const char *filename, grub_fat_dir_node_t *dir)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
@ -578,8 +830,13 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY);
info.case_insensitive = 1;
#ifdef MODE_EXFAT
if (!dir->have_stream)
return 0;
#else
if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
return 0;
#endif
if (*dirname == '\0' && call_hook)
return hook (filename, &info);
@ -587,9 +844,14 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
{
found = 1;
data->attr = dir->attr;
#ifdef MODE_EXFAT
data->file_size = dir->file_size;
data->file_cluster = dir->first_cluster;
#else
data->file_size = grub_le_to_cpu32 (dir->file_size);
data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16)
| grub_le_to_cpu16 (dir->first_cluster_low));
#endif
data->cur_cluster_num = ~0U;
if (call_hook)
@ -745,14 +1007,68 @@ grub_fat_close (grub_file_t file)
return grub_errno;
}
#ifdef MODE_EXFAT
static grub_err_t
grub_fat_label (grub_device_t device, char **label)
{
struct grub_fat_dir_entry dir;
grub_ssize_t offset = -sizeof(dir);
struct grub_fat_data *data;
grub_disk_t disk = device->disk;
data = grub_fat_mount (disk);
if (! data)
return grub_errno;
*label = NULL;
while (1)
{
offset += sizeof (dir);
if (grub_fat_read_data (disk, data, 0,
offset, sizeof (dir), (char *) &dir)
!= sizeof (dir))
break;
if (dir.entry_type == 0)
break;
if (!(dir.entry_type & 0x80))
continue;
/* Volume label. */
if (dir.entry_type == 0x83)
{
grub_size_t chc;
*label = grub_malloc (ARRAY_SIZE (dir.type_specific.volume_label.str)
* GRUB_MAX_UTF8_PER_UTF16 + 1);
if (!*label)
{
grub_free (data);
return grub_errno;
}
chc = dir.type_specific.volume_label.character_count;
if (chc > ARRAY_SIZE (dir.type_specific.volume_label.str))
chc = ARRAY_SIZE (dir.type_specific.volume_label.str);
*grub_utf16_to_utf8 ((grub_uint8_t *) *label,
dir.type_specific.volume_label.str, chc) = '\0';
}
}
grub_free (data);
return grub_errno;
}
#else
static grub_err_t
grub_fat_label (grub_device_t device, char **label)
{
struct grub_fat_data *data;
grub_disk_t disk = device->disk;
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
auto int iter_hook (const char *filename, grub_fat_dir_node_t *dir);
int iter_hook (const char *filename, grub_fat_dir_node_t *dir)
{
if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID)
{
@ -787,6 +1103,8 @@ grub_fat_label (grub_device_t device, char **label)
return grub_errno;
}
#endif
static grub_err_t
grub_fat_uuid (grub_device_t device, char **uuid)
{
@ -798,9 +1116,12 @@ grub_fat_uuid (grub_device_t device, char **uuid)
data = grub_fat_mount (disk);
if (data)
{
char *ptr;
*uuid = grub_xasprintf ("%04x-%04x",
(grub_uint16_t) (data->uuid >> 16),
(grub_uint16_t) data->uuid);
for (ptr = *uuid; ptr && *ptr; ptr++)
*ptr = grub_toupper (*ptr);
}
else
*uuid = NULL;
@ -814,7 +1135,11 @@ grub_fat_uuid (grub_device_t device, char **uuid)
static struct grub_fs grub_fat_fs =
{
#ifdef MODE_EXFAT
.name = "exfat",
#else
.name = "fat",
#endif
.dir = grub_fat_dir,
.open = grub_fat_open,
.read = grub_fat_read,
@ -822,18 +1147,31 @@ static struct grub_fs grub_fat_fs =
.label = grub_fat_label,
.uuid = grub_fat_uuid,
#ifdef GRUB_UTIL
#ifdef MODE_EXFAT
/* ExFAT BPB is 30 larger than FAT32 one. */
.reserved_first_sector = 0,
#else
.reserved_first_sector = 1,
#endif
#endif
.next = 0
};
#ifdef MODE_EXFAT
GRUB_MOD_INIT(exfat)
#else
GRUB_MOD_INIT(fat)
#endif
{
COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
grub_fs_register (&grub_fat_fs);
my_mod = mod;
}
#ifdef MODE_EXFAT
GRUB_MOD_FINI(exfat)
#else
GRUB_MOD_FINI(fat)
#endif
{
grub_fs_unregister (&grub_fat_fs);
}

View file

@ -61,7 +61,6 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
char fpath[grub_strlen (currpath) + 1];
char *name = fpath;
char *next;
// unsigned int pos = 0;
enum grub_fshelp_filetype type = GRUB_FSHELP_DIR;
grub_fshelp_node_t currnode = currroot;
grub_fshelp_node_t oldnode = currroot;
@ -85,7 +84,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
if (filetype == GRUB_FSHELP_UNKNOWN ||
(grub_strcmp (name, filename) &&
(! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
grub_strncasecmp (name, filename, GRUB_LONG_MAX))))
grub_strcasecmp (name, filename))))
{
grub_free (node);
return 0;

View file

@ -244,22 +244,24 @@ static grub_ssize_t
grub_hfs_read_file (struct grub_hfs_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
grub_off_t pos, grub_size_t len, char *buf)
{
int i;
int blockcnt;
grub_off_t i;
grub_off_t blockcnt;
blockcnt = ((len + pos)
+ data->blksz - 1) / data->blksz;
blockcnt = grub_divmod64 (((len + pos)
+ data->blksz - 1), data->blksz, 0);
for (i = pos / data->blksz; i < blockcnt; i++)
for (i = grub_divmod64 (pos, data->blksz, 0); i < blockcnt; i++)
{
int blknr;
int blockoff = pos % data->blksz;
int blockend = data->blksz;
grub_disk_addr_t blknr;
grub_off_t blockoff;
grub_off_t blockend = data->blksz;
int skipfirst = 0;
grub_divmod64 (pos, data->blksz, &blockoff);
blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1);
if (grub_errno)
return -1;
@ -267,7 +269,7 @@ grub_hfs_read_file (struct grub_hfs_data *data,
/* Last block. */
if (i == blockcnt - 1)
{
blockend = (len + pos) % data->blksz;
grub_divmod64 ((len + pos), data->blksz, &blockend);
/* The last portion is exactly EXT2_BLOCK_SIZE (data). */
if (! blockend)
@ -275,7 +277,7 @@ grub_hfs_read_file (struct grub_hfs_data *data,
}
/* First block. */
if (i == pos / data->blksz)
if (i == grub_divmod64 (pos, data->blksz, 0))
{
skipfirst = blockoff;
blockend -= skipfirst;
@ -748,10 +750,7 @@ grub_hfs_find_node (struct grub_hfs_data *data, char *key,
entry. In case of a non-leaf mode it will be used to lookup
the rest of the tree. */
if (cmp <= 0)
{
grub_uint32_t *node = (grub_uint32_t *) rec->data;
found = grub_be_to_cpu32 (*node);
}
found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data));
else /* The key can not be found in the tree. */
return 1;
@ -815,7 +814,7 @@ grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx,
struct grub_hfs_catalog_key *ckey = rec->key;
if (grub_hfs_cmp_catkeys (rec->key, (void *) &key) <= 0)
found = grub_be_to_cpu32 (*(grub_uint32_t *) rec->data);
found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data));
if (hnd->type == 0xFF && ckey->strlen > 0)
{
@ -863,6 +862,203 @@ grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx,
return grub_errno;
}
#define MAX_UTF8_PER_MAC_ROMAN 3
static const char macroman[0x80][MAX_UTF8_PER_MAC_ROMAN + 1] =
{
/* 80 */ "\xc3\x84",
/* 81 */ "\xc3\x85",
/* 82 */ "\xc3\x87",
/* 83 */ "\xc3\x89",
/* 84 */ "\xc3\x91",
/* 85 */ "\xc3\x96",
/* 86 */ "\xc3\x9c",
/* 87 */ "\xc3\xa1",
/* 88 */ "\xc3\xa0",
/* 89 */ "\xc3\xa2",
/* 8A */ "\xc3\xa4",
/* 8B */ "\xc3\xa3",
/* 8C */ "\xc3\xa5",
/* 8D */ "\xc3\xa7",
/* 8E */ "\xc3\xa9",
/* 8F */ "\xc3\xa8",
/* 90 */ "\xc3\xaa",
/* 91 */ "\xc3\xab",
/* 92 */ "\xc3\xad",
/* 93 */ "\xc3\xac",
/* 94 */ "\xc3\xae",
/* 95 */ "\xc3\xaf",
/* 96 */ "\xc3\xb1",
/* 97 */ "\xc3\xb3",
/* 98 */ "\xc3\xb2",
/* 99 */ "\xc3\xb4",
/* 9A */ "\xc3\xb6",
/* 9B */ "\xc3\xb5",
/* 9C */ "\xc3\xba",
/* 9D */ "\xc3\xb9",
/* 9E */ "\xc3\xbb",
/* 9F */ "\xc3\xbc",
/* A0 */ "\xe2\x80\xa0",
/* A1 */ "\xc2\xb0",
/* A2 */ "\xc2\xa2",
/* A3 */ "\xc2\xa3",
/* A4 */ "\xc2\xa7",
/* A5 */ "\xe2\x80\xa2",
/* A6 */ "\xc2\xb6",
/* A7 */ "\xc3\x9f",
/* A8 */ "\xc2\xae",
/* A9 */ "\xc2\xa9",
/* AA */ "\xe2\x84\xa2",
/* AB */ "\xc2\xb4",
/* AC */ "\xc2\xa8",
/* AD */ "\xe2\x89\xa0",
/* AE */ "\xc3\x86",
/* AF */ "\xc3\x98",
/* B0 */ "\xe2\x88\x9e",
/* B1 */ "\xc2\xb1",
/* B2 */ "\xe2\x89\xa4",
/* B3 */ "\xe2\x89\xa5",
/* B4 */ "\xc2\xa5",
/* B5 */ "\xc2\xb5",
/* B6 */ "\xe2\x88\x82",
/* B7 */ "\xe2\x88\x91",
/* B8 */ "\xe2\x88\x8f",
/* B9 */ "\xcf\x80",
/* BA */ "\xe2\x88\xab",
/* BB */ "\xc2\xaa",
/* BC */ "\xc2\xba",
/* BD */ "\xce\xa9",
/* BE */ "\xc3\xa6",
/* BF */ "\xc3\xb8",
/* C0 */ "\xc2\xbf",
/* C1 */ "\xc2\xa1",
/* C2 */ "\xc2\xac",
/* C3 */ "\xe2\x88\x9a",
/* C4 */ "\xc6\x92",
/* C5 */ "\xe2\x89\x88",
/* C6 */ "\xe2\x88\x86",
/* C7 */ "\xc2\xab",
/* C8 */ "\xc2\xbb",
/* C9 */ "\xe2\x80\xa6",
/* CA */ "\xc2\xa0",
/* CB */ "\xc3\x80",
/* CC */ "\xc3\x83",
/* CD */ "\xc3\x95",
/* CE */ "\xc5\x92",
/* CF */ "\xc5\x93",
/* D0 */ "\xe2\x80\x93",
/* D1 */ "\xe2\x80\x94",
/* D2 */ "\xe2\x80\x9c",
/* D3 */ "\xe2\x80\x9d",
/* D4 */ "\xe2\x80\x98",
/* D5 */ "\xe2\x80\x99",
/* D6 */ "\xc3\xb7",
/* D7 */ "\xe2\x97\x8a",
/* D8 */ "\xc3\xbf",
/* D9 */ "\xc5\xb8",
/* DA */ "\xe2\x81\x84",
/* DB */ "\xe2\x82\xac",
/* DC */ "\xe2\x80\xb9",
/* DD */ "\xe2\x80\xba",
/* DE */ "\xef\xac\x81",
/* DF */ "\xef\xac\x82",
/* E0 */ "\xe2\x80\xa1",
/* E1 */ "\xc2\xb7",
/* E2 */ "\xe2\x80\x9a",
/* E3 */ "\xe2\x80\x9e",
/* E4 */ "\xe2\x80\xb0",
/* E5 */ "\xc3\x82",
/* E6 */ "\xc3\x8a",
/* E7 */ "\xc3\x81",
/* E8 */ "\xc3\x8b",
/* E9 */ "\xc3\x88",
/* EA */ "\xc3\x8d",
/* EB */ "\xc3\x8e",
/* EC */ "\xc3\x8f",
/* ED */ "\xc3\x8c",
/* EE */ "\xc3\x93",
/* EF */ "\xc3\x94",
/* F0 */ "\xef\xa3\xbf",
/* F1 */ "\xc3\x92",
/* F2 */ "\xc3\x9a",
/* F3 */ "\xc3\x9b",
/* F4 */ "\xc3\x99",
/* F5 */ "\xc4\xb1",
/* F6 */ "\xcb\x86",
/* F7 */ "\xcb\x9c",
/* F8 */ "\xc2\xaf",
/* F9 */ "\xcb\x98",
/* FA */ "\xcb\x99",
/* FB */ "\xcb\x9a",
/* FC */ "\xc2\xb8",
/* FD */ "\xcb\x9d",
/* FE */ "\xcb\x9b",
/* FF */ "\xcb\x87",
};
static void
macroman_to_utf8 (char *to, const grub_uint8_t *from, grub_size_t len)
{
char *optr = to;
const grub_uint8_t *iptr;
for (iptr = from; iptr < from + len && *iptr; iptr++)
{
/* Translate '/' to ':' as per HFS spec. */
if (*iptr == '/')
{
*optr++ = ':';
continue;
}
if (!(*iptr & 0x80))
{
*optr++ = *iptr;
continue;
}
optr = grub_stpcpy (optr, macroman[*iptr & 0x7f]);
}
*optr = 0;
}
static grub_ssize_t
utf8_to_macroman (grub_uint8_t *to, const char *from)
{
grub_uint8_t *end = to + 31;
grub_uint8_t *optr = to;
const char *iptr = from;
while (*iptr && optr < end)
{
int i, clen;
/* Translate ':' to '/' as per HFS spec. */
if (*iptr == ':')
{
*optr++ = '/';
iptr++;
continue;
}
if (!(*iptr & 0x80))
{
*optr++ = *iptr++;
continue;
}
clen = 2;
if ((*iptr & 0xf0) == 0xe0)
clen++;
for (i = 0; i < 0x80; i++)
if (grub_memcmp (macroman[i], iptr, clen) == 0)
break;
if (i == 0x80)
break;
*optr++ = i | 0x80;
iptr += clen;
}
/* Too long or not encodable. */
if (*iptr)
return -1;
return optr - to;
}
/* Find a file or directory with the pathname PATH in the filesystem
DATA. Return the file record in RETDATA when it is non-zero.
@ -897,6 +1093,7 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path,
while (path && grub_strlen (path))
{
grub_ssize_t slen;
if (fdrec.frec.type != GRUB_HFS_FILETYPE_DIR)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
@ -914,8 +1111,13 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path,
struct grub_hfs_catalog_key key;
key.parent_dir = grub_cpu_to_be32 (inode);
key.strlen = grub_strlen (path);
grub_strcpy ((char *) (key.str), path);
slen = utf8_to_macroman (key.str, path);
if (slen < 0)
{
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path);
goto fail;
}
key.strlen = slen;
/* Lookup this node. */
if (! grub_hfs_find_node (data, (char *) &key, data->cat_root,
@ -956,14 +1158,21 @@ grub_hfs_dir (grub_device_t device, const char *path,
int dir_hook (struct grub_hfs_record *rec)
{
char fname[32] = { 0 };
struct grub_hfs_dirrec *drec = rec->data;
struct grub_hfs_filerec *frec = rec->data;
struct grub_hfs_catalog_key *ckey = rec->key;
char fname[sizeof (ckey->str) * MAX_UTF8_PER_MAC_ROMAN + 1] = { 0 };
struct grub_dirhook_info info;
grub_size_t len;
grub_memset (&info, 0, sizeof (info));
grub_strncpy (fname, (char *) (ckey->str), ckey->strlen);
len = ckey->strlen;
if (len > sizeof (ckey->str))
len = sizeof (ckey->str);
macroman_to_utf8 (fname, ckey->str, len);
info.case_insensitive = 1;
if (drec->type == GRUB_HFS_FILETYPE_DIR)
{
@ -1079,8 +1288,15 @@ grub_hfs_label (grub_device_t device, char **label)
data = grub_hfs_mount (device->disk);
if (data)
*label = grub_strndup ((char *) (data->sblock.volname + 1),
*data->sblock.volname);
{
grub_size_t len = data->sblock.volname[0];
if (len > sizeof (data->sblock.volname) - 1)
len = sizeof (data->sblock.volname) - 1;
*label = grub_malloc (len * MAX_UTF8_PER_MAC_ROMAN + 1);
if (*label)
macroman_to_utf8 (*label, data->sblock.volname + 1,
len + 1);
}
else
*label = 0;

View file

@ -181,7 +181,8 @@ enum grub_hfsplus_filetype
struct grub_hfsplus_catkey_internal
{
grub_uint32_t parent;
char *name;
const grub_uint16_t *name;
grub_size_t namelen;
};
/* Internal representation of an extent overflow key. */
@ -214,7 +215,7 @@ struct grub_fshelp_node
struct grub_hfsplus_btree
{
grub_uint32_t root;
int nodesize;
grub_size_t nodesize;
/* Catalog file node. */
struct grub_fshelp_node file;
@ -236,7 +237,7 @@ struct grub_hfsplus_data
/* This is the offset into the physical disk for an embedded HFS+
filesystem (one inside a plain HFS wrapper). */
int embedded_offset;
grub_disk_addr_t embedded_offset;
int case_sensitive;
};
@ -245,15 +246,14 @@ static grub_dl_t my_mod;
/* Return the offset of the record with the index INDEX, in the node
NODE which is part of the B+ tree BTREE. */
static inline unsigned int
static inline grub_off_t
grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_btnode *node, int index)
{
char *cnode = (char *) node;
grub_uint16_t *recptr;
recptr = (grub_uint16_t *) (&cnode[btree->nodesize
- index * sizeof (grub_uint16_t) - 2]);
return grub_be_to_cpu16 (*recptr);
void *recptr;
recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]);
return grub_be_to_cpu16 (grub_get_unaligned16 (recptr));
}
/* Return a pointer to the record with the index INDEX, in the node
@ -263,7 +263,7 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_btnode *node, int index)
{
char *cnode = (char *) node;
unsigned int offset;
grub_off_t offset;
offset = grub_hfsplus_btree_recoffset (btree, node, index);
return (struct grub_hfsplus_key *) &cnode[offset];
}
@ -272,12 +272,12 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
/* Find the extent that points to FILEBLOCK. If it is not in one of
the 8 extents described by EXTENT, return -1. In that case set
FILEBLOCK to the next block. */
static int
static grub_disk_addr_t
grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
int *fileblock)
grub_disk_addr_t *fileblock)
{
int i;
grub_size_t blksleft = *fileblock;
grub_disk_addr_t blksleft = *fileblock;
/* First lookup the file in the given extents. */
for (i = 0; i < 8; i++)
@ -288,7 +288,7 @@ grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
}
*fileblock = blksleft;
return -1;
return 0xffffffffffffffffULL;
}
static grub_err_t
@ -296,7 +296,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_key_internal *key,
int (*compare_keys) (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb),
struct grub_hfsplus_btnode **matchnode, int *keyoffset);
struct grub_hfsplus_btnode **matchnode,
grub_off_t *keyoffset);
static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb);
@ -307,15 +308,15 @@ static grub_disk_addr_t
grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
struct grub_hfsplus_btnode *nnode = 0;
int blksleft = fileblock;
grub_disk_addr_t blksleft = fileblock;
struct grub_hfsplus_extent *extents = &node->extents[0];
while (1)
{
struct grub_hfsplus_extkey *key;
struct grub_hfsplus_extkey_internal extoverflow;
int blk;
int ptr;
struct grub_hfsplus_key_internal extoverflow;
grub_disk_addr_t blk;
grub_off_t ptr;
/* Try to find this block in the current set of extents. */
blk = grub_hfsplus_find_block (extents, &blksleft);
@ -325,7 +326,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
grub_free (nnode);
nnode = 0;
if (blk != -1)
if (blk != 0xffffffffffffffffULL)
return (blk
+ (node->data->embedded_offset >> (node->data->log2blksize
- GRUB_DISK_SECTOR_BITS)));
@ -341,11 +342,11 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
}
/* Set up the key to look for in the extent overflow file. */
extoverflow.fileid = node->fileid;
extoverflow.start = fileblock - blksleft;
extoverflow.extkey.fileid = node->fileid;
extoverflow.extkey.start = fileblock - blksleft;
if (grub_hfsplus_btree_search (&node->data->extoverflow_tree,
(struct grub_hfsplus_key_internal *) &extoverflow,
&extoverflow,
grub_hfsplus_cmp_extkey, &nnode, &ptr))
{
grub_error (GRUB_ERR_READ_ERROR,
@ -376,7 +377,7 @@ static grub_ssize_t
grub_hfsplus_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
grub_off_t 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,
@ -411,9 +412,9 @@ grub_hfsplus_mount (grub_disk_t disk)
data->embedded_offset = 0;
if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC)
{
int extent_start;
int ablk_size;
int ablk_start;
grub_disk_addr_t extent_start;
grub_disk_addr_t ablk_size;
grub_disk_addr_t ablk_start;
/* See if there's an embedded HFS+ filesystem. */
if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC)
@ -518,9 +519,8 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya,
{
struct grub_hfsplus_catkey *catkey_a = &keya->catkey;
struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey;
char *filename;
int i;
int diff;
grub_size_t len;
/* Safe unsigned comparison */
grub_uint32_t aparent = grub_be_to_cpu32 (catkey_a->parent);
@ -529,29 +529,36 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya,
if (aparent < catkey_b->parent)
return -1;
/* Change the filename in keya so the endianness is correct. */
for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++)
catkey_a->name[i] = grub_be_to_cpu16 (catkey_a->name[i]);
len = grub_be_to_cpu16 (catkey_a->namelen);
if (len > catkey_b->namelen)
len = catkey_b->namelen;
diff = grub_memcmp (catkey_a->name, catkey_b->name,
len * sizeof (catkey_a->name[0]));
if (diff == 0)
diff = grub_be_to_cpu16 (catkey_a->namelen) - catkey_b->namelen;
filename = grub_malloc (grub_be_to_cpu16 (catkey_a->namelen) + 1);
if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey_a->name,
grub_be_to_cpu16 (catkey_a->namelen)))
return -1; /* XXX: This error never occurs, but in case it happens
just skip this entry. */
diff = grub_strncmp (filename, catkey_b->name,
grub_be_to_cpu16 (catkey_a->namelen));
grub_free (filename);
/* The endianness was changed to host format, change it back to
whatever it was. */
for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++)
catkey_a->name[i] = grub_cpu_to_be16 (catkey_a->name[i]);
return diff;
}
/* Compare the on disk catalog key KEYA with the catalog key we are
looking for (KEYB). */
static int
grub_hfsplus_cmp_catkey_id (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb)
{
struct grub_hfsplus_catkey *catkey_a = &keya->catkey;
struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey;
/* Safe unsigned comparison */
grub_uint32_t aparent = grub_be_to_cpu32 (catkey_a->parent);
if (aparent > catkey_b->parent)
return 1;
if (aparent < catkey_b->parent)
return -1;
return 0;
}
/* Compare the on disk extent overflow key KEYA with the extent
overflow key we are looking for (KEYB). */
static int
@ -601,10 +608,10 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
static int
grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_btnode *first_node,
int first_rec,
grub_disk_addr_t first_rec,
int (*hook) (void *record))
{
int rec;
grub_disk_addr_t rec;
for (;;)
{
@ -642,12 +649,13 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_key_internal *key,
int (*compare_keys) (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb),
struct grub_hfsplus_btnode **matchnode, int *keyoffset)
struct grub_hfsplus_btnode **matchnode,
grub_off_t *keyoffset)
{
grub_uint64_t currnode;
char *node;
struct grub_hfsplus_btnode *nodedesc;
int rec;
grub_disk_addr_t rec;
node = grub_malloc (btree->nodesize);
if (! node)
@ -660,7 +668,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
/* Read a node. */
if (grub_hfsplus_read_file (&btree->file, 0,
(long)currnode * (long)btree->nodesize,
(grub_disk_addr_t) currnode
* (grub_disk_addr_t) btree->nodesize,
btree->nodesize, (char *) node) <= 0)
{
grub_free (node);
@ -689,7 +698,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
}
else if (nodedesc->type == GRUB_HFSPLUS_BTNODE_TYPE_INDEX)
{
grub_uint32_t *pointer;
void *pointer;
/* The place where the key could have been found didn't
contain the key. This means that the previous match
@ -701,10 +710,10 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
that we are looking for. The last match that is
found will be used to locate the child which can
contain the record. */
pointer = (grub_uint32_t *) ((char *) currkey
+ grub_be_to_cpu16 (currkey->keylen)
+ 2);
currnode = grub_be_to_cpu32 (*pointer);
pointer = ((char *) currkey
+ grub_be_to_cpu16 (currkey->keylen)
+ 2);
currnode = grub_be_to_cpu32 (grub_get_unaligned32 (pointer));
match = 1;
}
}
@ -770,53 +779,51 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
if (type == GRUB_FSHELP_UNKNOWN)
return 0;
filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen)
* GRUB_MAX_UTF8_PER_UTF16 + 1);
if (! filename)
return 0;
/* Make sure the byte order of the UTF16 string is correct. */
for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++)
{
catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]);
if (catkey->name[i] == '/')
catkey->name[i] = ':';
/* If the name is obviously invalid, skip this node. */
if (catkey->name[i] == 0)
return 0;
}
filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) + 1);
if (! filename)
return 0;
if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name,
grub_be_to_cpu16 (catkey->namelen)))
{
grub_free (filename);
return 0;
}
filename[grub_be_to_cpu16 (catkey->namelen)] = '\0';
*grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name,
grub_be_to_cpu16 (catkey->namelen)) = '\0';
/* Restore the byte order to what it was previously. */
for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++)
catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]);
{
if (catkey->name[i] == ':')
catkey->name[i] = '/';
catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]);
}
/* hfs+ is case insensitive. */
if (! dir->data->case_sensitive)
type |= GRUB_FSHELP_CASE_INSENSITIVE;
/* Only accept valid nodes. */
if (grub_strlen (filename) == grub_be_to_cpu16 (catkey->namelen))
{
/* A valid node is found; setup the node and call the
callback function. */
node = grub_malloc (sizeof (*node));
node->data = dir->data;
/* A valid node is found; setup the node and call the
callback function. */
node = grub_malloc (sizeof (*node));
node->data = dir->data;
grub_memcpy (node->extents, fileinfo->data.extents,
sizeof (node->extents));
node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800;
node->size = grub_be_to_cpu64 (fileinfo->data.size);
node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
grub_memcpy (node->extents, fileinfo->data.extents,
sizeof (node->extents));
node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800;
node->size = grub_be_to_cpu64 (fileinfo->data.size);
node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
ret = hook (filename, type, node);
}
ret = hook (filename, type, node);
grub_free (filename);
@ -825,11 +832,12 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
struct grub_hfsplus_key_internal intern;
struct grub_hfsplus_btnode *node;
int ptr;
grub_disk_addr_t ptr;
/* Create a key that points to the first entry in the directory. */
intern.catkey.parent = dir->fileid;
intern.catkey.name = "";
intern.catkey.name = 0;
intern.catkey.namelen = 0;
/* First lookup the first entry. */
if (grub_hfsplus_btree_search (&dir->data->catalog_tree, &intern,
@ -894,7 +902,6 @@ grub_hfsplus_close (grub_file_t file)
return GRUB_ERR_NONE;
}
/* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t
grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
@ -902,13 +909,10 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
struct grub_hfsplus_data *data =
(struct grub_hfsplus_data *) file->data;
int size = grub_hfsplus_read_file (&data->opened_file, file->read_hook,
return grub_hfsplus_read_file (&data->opened_file, file->read_hook,
file->offset, len, buf);
return size;
}
static grub_err_t
grub_hfsplus_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
@ -963,13 +967,59 @@ grub_hfsplus_dir (grub_device_t device, const char *path,
static grub_err_t
grub_hfsplus_label (grub_device_t device __attribute__((unused))
, char **label __attribute__((unused)))
grub_hfsplus_label (grub_device_t device, char **label)
{
/* XXX: It's not documented how to read a label. */
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"reading the label of a HFS+ "
"partition is not implemented");
struct grub_hfsplus_data *data;
grub_disk_t disk = device->disk;
struct grub_hfsplus_catkey *catkey;
int i, label_len;
struct grub_hfsplus_key_internal intern;
struct grub_hfsplus_btnode *node;
grub_disk_addr_t ptr;
*label = 0;
data = grub_hfsplus_mount (disk);
if (!data)
return grub_errno;
/* Create a key that points to the label. */
intern.catkey.parent = 1;
intern.catkey.name = 0;
intern.catkey.namelen = 0;
/* First lookup the first entry. */
if (grub_hfsplus_btree_search (&data->catalog_tree, &intern,
grub_hfsplus_cmp_catkey_id, &node, &ptr))
{
grub_free (data);
return 0;
}
catkey = (struct grub_hfsplus_catkey *)
grub_hfsplus_btree_recptr (&data->catalog_tree, node, 0);
label_len = grub_be_to_cpu16 (catkey->namelen);
for (i = 0; i < label_len; i++)
{
catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]);
/* If the name is obviously invalid, skip this node. */
if (catkey->name[i] == 0)
return 0;
}
*label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1);
if (! *label)
return grub_errno;
*grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name,
label_len) = '\0';
grub_free (node);
grub_free (data);
return GRUB_ERR_NONE;
}
/* Get mtime. */

View file

@ -149,22 +149,29 @@ struct grub_iso9660_data
{
struct grub_iso9660_primary_voldesc voldesc;
grub_disk_t disk;
unsigned int first_sector;
int rockridge;
int susp_skip;
int joliet;
struct grub_fshelp_node *node;
};
struct grub_fshelp_node
{
struct grub_iso9660_data *data;
struct grub_iso9660_dir dirent;
unsigned int size;
unsigned int blk;
unsigned int dir_blk;
unsigned int dir_off;
grub_size_t have_dirents, alloc_dirents;
int have_symlink;
struct grub_iso9660_dir dirents[8];
char symlink[0];
};
enum
{
FLAG_TYPE_PLAIN = 0,
FLAG_TYPE_DIR = 2,
FLAG_TYPE = 3,
FLAG_MORE_EXTENTS = 0x80
};
static grub_dl_t my_mod;
@ -214,35 +221,77 @@ iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix)
return 1;
}
static grub_err_t
read_node (grub_fshelp_node_t node, grub_off_t off, grub_size_t len, char *buf)
{
grub_size_t i = 0;
while (len > 0)
{
grub_size_t toread;
grub_err_t err;
while (i < node->have_dirents
&& off >= grub_le_to_cpu32 (node->dirents[i].size))
{
off -= grub_le_to_cpu32 (node->dirents[i].size);
i++;
}
if (i == node->have_dirents)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "read out of range");
toread = grub_le_to_cpu32 (node->dirents[i].size);
if (toread > len)
toread = len;
err = grub_disk_read (node->data->disk,
((grub_disk_addr_t) grub_le_to_cpu32 (node->dirents[i].first_sector)) << GRUB_ISO9660_LOG2_BLKSZ,
off, toread, buf);
if (err)
return err;
len -= toread;
off += toread;
buf += toread;
}
return GRUB_ERR_NONE;
}
/* Iterate over the susp entries, starting with block SUA_BLOCK on the
offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for
every entry. */
static grub_err_t
grub_iso9660_susp_iterate (struct grub_iso9660_data *data,
int sua_block, int sua_pos, int sua_size,
grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off,
grub_ssize_t sua_size,
grub_err_t (*hook)
(struct grub_iso9660_susp_entry *entry))
{
char *sua;
struct grub_iso9660_susp_entry *entry;
grub_disk_addr_t ce_block;
int is_ce = 0;
auto grub_err_t load_sua (void);
/* Load a part of the System Usage Area. */
grub_err_t load_sua (void)
{
grub_err_t err;
sua = grub_malloc (sua_size);
if (!sua)
return grub_errno;
if (grub_disk_read (data->disk, sua_block, sua_pos,
sua_size, sua))
return grub_errno;
if (is_ce)
err = grub_disk_read (node->data->disk, ce_block, off,
sua_size, sua);
else
err = read_node (node, off, sua_size, sua);
if (err)
return err;
entry = (struct grub_iso9660_susp_entry *) sua;
return 0;
}
if (sua_size <= 0)
return GRUB_ERR_NONE;
if (load_sua ())
return grub_errno;
@ -259,10 +308,11 @@ grub_iso9660_susp_iterate (struct grub_iso9660_data *data,
{
struct grub_iso9660_susp_ce *ce;
is_ce = 1;
ce = (struct grub_iso9660_susp_ce *) entry;
sua_size = grub_le_to_cpu32 (ce->len);
sua_pos = grub_le_to_cpu32 (ce->off);
sua_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ;
off = grub_le_to_cpu32 (ce->off);
ce_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ;
grub_free (sua);
if (load_sua ())
@ -281,34 +331,32 @@ grub_iso9660_susp_iterate (struct grub_iso9660_data *data,
}
static char *
grub_iso9660_convert_string (grub_uint16_t *us, int len)
grub_iso9660_convert_string (grub_uint8_t *us, int len)
{
char *p;
int i;
grub_uint16_t t[len];
p = grub_malloc (len * 4 + 1);
p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1);
if (! p)
return p;
for (i=0; i<len; i++)
us[i] = grub_be_to_cpu16 (us[i]);
t[i] = grub_be_to_cpu16 (grub_get_unaligned16 (us + 2 * i));
*grub_utf16_to_utf8 ((grub_uint8_t *) p, us, len) = '\0';
*grub_utf16_to_utf8 ((grub_uint8_t *) p, t, len) = '\0';
return p;
}
static struct grub_iso9660_data *
grub_iso9660_mount (grub_disk_t disk)
static grub_err_t
set_rockridge (struct grub_iso9660_data *data)
{
struct grub_iso9660_data *data = 0;
struct grub_iso9660_dir rootdir;
int sua_pos;
int sua_size;
char *sua;
struct grub_iso9660_dir rootdir;
struct grub_iso9660_susp_entry *entry;
struct grub_iso9660_primary_voldesc voldesc;
int block;
auto grub_err_t susp_iterate (struct grub_iso9660_susp_entry *);
@ -324,6 +372,74 @@ grub_iso9660_mount (grub_disk_t disk)
return 0;
}
data->rockridge = 0;
/* Read the system use area and test it to see if SUSP is
supported. */
if (grub_disk_read (data->disk,
(grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), 0,
sizeof (rootdir), (char *) &rootdir))
return grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
sua_pos = (sizeof (rootdir) + rootdir.namelen
+ (rootdir.namelen % 2) - 1);
sua_size = rootdir.len - sua_pos;
if (!sua_size)
return GRUB_ERR_NONE;
sua = grub_malloc (sua_size);
if (! sua)
return grub_errno;
if (grub_disk_read (data->disk,
(grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), sua_pos,
sua_size, sua))
{
grub_free (sua);
return grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
}
entry = (struct grub_iso9660_susp_entry *) sua;
/* Test if the SUSP protocol is used on this filesystem. */
if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0)
{
struct grub_fshelp_node rootnode;
rootnode.data = data;
rootnode.alloc_dirents = ARRAY_SIZE (rootnode.dirents);
rootnode.have_dirents = 1;
rootnode.have_symlink = 0;
rootnode.dirents[0] = data->voldesc.rootdir;
/* The 2nd data byte stored how many bytes are skipped every time
to get to the SUA (System Usage Area). */
data->susp_skip = entry->data[2];
entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len);
/* Iterate over the entries in the SUA area to detect
extensions. */
if (grub_iso9660_susp_iterate (&rootnode,
sua_pos, sua_size, susp_iterate))
{
grub_free (sua);
return grub_errno;
}
}
grub_free (sua);
return GRUB_ERR_NONE;
}
static struct grub_iso9660_data *
grub_iso9660_mount (grub_disk_t disk)
{
struct grub_iso9660_data *data = 0;
struct grub_iso9660_primary_voldesc voldesc;
int block;
data = grub_zalloc (sizeof (struct grub_iso9660_data));
if (! data)
return 0;
@ -351,9 +467,11 @@ grub_iso9660_mount (grub_disk_t disk)
}
if (voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_PRIMARY)
copy_voldesc = 1;
else if ((voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_SUPP) &&
(voldesc.escape[0] == 0x25) && (voldesc.escape[1] == 0x2f) &&
copy_voldesc = 1;
else if (!data->rockridge
&& (voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_SUPP)
&& (voldesc.escape[0] == 0x25) && (voldesc.escape[1] == 0x2f)
&&
((voldesc.escape[2] == 0x40) || /* UCS-2 Level 1. */
(voldesc.escape[2] == 0x43) || /* UCS-2 Level 2. */
(voldesc.escape[2] == 0x45))) /* UCS-2 Level 3. */
@ -363,57 +481,16 @@ grub_iso9660_mount (grub_disk_t disk)
}
if (copy_voldesc)
grub_memcpy((char *) &data->voldesc, (char *) &voldesc,
sizeof (struct grub_iso9660_primary_voldesc));
{
grub_memcpy((char *) &data->voldesc, (char *) &voldesc,
sizeof (struct grub_iso9660_primary_voldesc));
if (set_rockridge (data))
goto fail;
}
block++;
} while (voldesc.voldesc.type != GRUB_ISO9660_VOLDESC_END);
/* Read the system use area and test it to see if SUSP is
supported. */
if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), 0,
sizeof (rootdir), (char *) &rootdir))
{
grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
goto fail;
}
sua_pos = (sizeof (rootdir) + rootdir.namelen
+ (rootdir.namelen % 2) - 1);
sua_size = rootdir.len - sua_pos;
sua = grub_malloc (sua_size);
if (! sua)
goto fail;
if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), sua_pos,
sua_size, sua))
{
grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
goto fail;
}
entry = (struct grub_iso9660_susp_entry *) sua;
/* Test if the SUSP protocol is used on this filesystem. */
if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0)
{
/* The 2nd data byte stored how many bytes are skipped every time
to get to the SUA (System Usage Area). */
data->susp_skip = entry->data[2];
entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len);
/* Iterate over the entries in the SUA area to detect
extensions. */
if (grub_iso9660_susp_iterate (data,
(grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ),
sua_pos, sua_size, susp_iterate))
goto fail;
}
return data;
fail:
@ -425,42 +502,125 @@ grub_iso9660_mount (grub_disk_t disk)
static char *
grub_iso9660_read_symlink (grub_fshelp_node_t node)
{
int sua_off;
int sua_size;
char *symlink = 0;
int addslash = 0;
return node->have_symlink
? grub_strdup (node->symlink
+ (node->have_dirents) * sizeof (node->dirents[0])
- sizeof (node->dirents)) : grub_strdup ("");
}
auto void add_part (const char *part, int len);
auto grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *);
static grub_off_t
get_node_size (grub_fshelp_node_t node)
{
grub_off_t ret = 0;
grub_size_t i;
for (i = 0; i < node->have_dirents; i++)
ret += grub_le_to_cpu32 (node->dirents[i].size);
return ret;
}
static int
grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_iso9660_dir dirent;
grub_off_t offset = 0;
char *filename = 0;
int filename_alloc = 0;
enum grub_fshelp_filetype type;
grub_off_t len;
char *symlink = 0;
/* Extend the symlink. */
void add_part (const char *part, int len)
{
int size = grub_strlen (symlink);
auto inline void __attribute__ ((always_inline)) add_part (const char *part,
int len2);
symlink = grub_realloc (symlink, size + len + 1);
auto inline void __attribute__ ((always_inline)) add_part (const char *part,
int len2)
{
int size = symlink ? grub_strlen (symlink) : 0;
symlink = grub_realloc (symlink, size + len2 + 1);
if (! symlink)
return;
grub_strncat (symlink, part, len);
symlink[size] = 0;
grub_strncat (symlink, part, len2);
}
/* Read in a symlink. */
grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *entry)
auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *);
grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry)
{
if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0)
/* The filename in the rock ridge entry. */
if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0)
{
/* The flags are stored at the data position 0, here the
filename type is stored. */
if (entry->data[0] & GRUB_ISO9660_RR_DOT)
filename = ".";
else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
filename = "..";
else if (entry->len >= 5)
{
grub_size_t size = 1, csize = 1;
char *old;
csize = size = entry->len - 5;
old = filename;
if (filename_alloc)
{
size += grub_strlen (filename);
filename = grub_realloc (filename, size + 1);
}
else
{
filename_alloc = 1;
filename = grub_zalloc (size + 1);
filename[0] = 0;
}
if (!filename)
{
filename = old;
return grub_errno;
}
filename_alloc = 1;
grub_strncat (filename, (char *) &entry->data[1], csize);
filename[size] = '\0';
}
}
/* The mode information (st_mode). */
else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0)
{
/* At position 0 of the PX record the st_mode information is
stored (little-endian). */
grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8))
& GRUB_ISO9660_FSTYPE_MASK);
switch (mode)
{
case GRUB_ISO9660_FSTYPE_DIR:
type = GRUB_FSHELP_DIR;
break;
case GRUB_ISO9660_FSTYPE_REG:
type = GRUB_FSHELP_REG;
break;
case GRUB_ISO9660_FSTYPE_SYMLINK:
type = GRUB_FSHELP_SYMLINK;
break;
default:
type = GRUB_FSHELP_UNKNOWN;
}
}
else if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0)
{
unsigned int pos = 1;
/* The symlink is not stored as a POSIX symlink, translate it. */
while (pos < grub_le_to_cpu32 (entry->len))
while (pos + sizeof (*entry) < grub_le_to_cpu32 (entry->len))
{
if (addslash)
{
add_part ("/", 1);
addslash = 0;
}
/* The current position is the `Component Flag'. */
switch (entry->data[pos] & 30)
{
@ -469,10 +629,10 @@ 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'. */
if (symlink && (entry->data[pos] & 1))
add_part ("/", 1);
add_part ((char *) &entry->data[pos + 2],
entry->data[pos + 1]);
if ((entry->data[pos] & 1))
addslash = 1;
break;
}
@ -502,109 +662,13 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node)
return 0;
}
sua_off = (sizeof (node->dirent) + node->dirent.namelen + 1
- (node->dirent.namelen % 2)
+ node->data->susp_skip);
sua_size = node->dirent.len - sua_off;
len = get_node_size (dir);
symlink = grub_malloc (1);
if (!symlink)
return 0;
*symlink = '\0';
if (grub_iso9660_susp_iterate (node->data, node->dir_blk,
node->dir_off + sua_off,
sua_size, susp_iterate_sl))
for (; offset < len; offset += dirent.len)
{
grub_free (symlink);
return 0;
}
symlink = 0;
return symlink;
}
static int
grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_iso9660_dir dirent;
unsigned int offset = 0;
char *filename;
int filename_alloc = 0;
enum grub_fshelp_filetype type;
auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *);
grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry)
{
/* The filename in the rock ridge entry. */
if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0)
{
/* The flags are stored at the data position 0, here the
filename type is stored. */
if (entry->data[0] & GRUB_ISO9660_RR_DOT)
filename = ".";
else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
filename = "..";
else
{
int size = 1;
if (filename)
{
size += grub_strlen (filename);
grub_realloc (filename,
grub_strlen (filename)
+ entry->len);
}
else
{
size = entry->len - 5;
filename = grub_zalloc (size + 1);
}
filename_alloc = 1;
grub_strncpy (filename, (char *) &entry->data[1], size);
filename[size] = '\0';
}
}
/* The mode information (st_mode). */
else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0)
{
/* At position 0 of the PX record the st_mode information is
stored (little-endian). */
grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8))
& GRUB_ISO9660_FSTYPE_MASK);
switch (mode)
{
case GRUB_ISO9660_FSTYPE_DIR:
type = GRUB_FSHELP_DIR;
break;
case GRUB_ISO9660_FSTYPE_REG:
type = GRUB_FSHELP_REG;
break;
case GRUB_ISO9660_FSTYPE_SYMLINK:
type = GRUB_FSHELP_SYMLINK;
break;
default:
type = GRUB_FSHELP_UNKNOWN;
}
}
return 0;
}
for (; offset < dir->size; offset += dirent.len)
{
if (grub_disk_read (dir->data->disk,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ offset / GRUB_DISK_SECTOR_SIZE,
offset % GRUB_DISK_SECTOR_SIZE,
sizeof (dirent), (char *) &dirent))
if (read_node (dir, offset, sizeof (dirent), (char *) &dirent))
return 0;
/* The end of the block, skip to the next one. */
@ -629,39 +693,30 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
type = GRUB_FSHELP_UNKNOWN;
if (dir->data->rockridge
&& grub_iso9660_susp_iterate (dir->data,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ (sua_off
/ GRUB_DISK_SECTOR_SIZE),
sua_off % GRUB_DISK_SECTOR_SIZE,
sua_size, susp_iterate_dir))
&& grub_iso9660_susp_iterate (dir, sua_off, sua_size,
susp_iterate_dir))
return 0;
/* Read the name. */
if (grub_disk_read (dir->data->disk,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ nameoffset / GRUB_DISK_SECTOR_SIZE,
nameoffset % GRUB_DISK_SECTOR_SIZE,
dirent.namelen, (char *) name))
if (read_node (dir, nameoffset, dirent.namelen, (char *) name))
return 0;
node = grub_malloc (sizeof (struct grub_fshelp_node));
if (!node)
return 0;
node->alloc_dirents = ARRAY_SIZE (node->dirents);
node->have_dirents = 1;
/* Setup a new node. */
node->data = dir->data;
node->size = grub_le_to_cpu32 (dirent.size);
node->blk = grub_le_to_cpu32 (dirent.first_sector);
node->dir_blk = ((dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ offset / GRUB_DISK_SECTOR_SIZE);
node->dir_off = offset % GRUB_DISK_SECTOR_SIZE;
node->have_symlink = 0;
/* If the filetype was not stored using rockridge, use
whatever is stored in the iso9660 filesystem. */
if (type == GRUB_FSHELP_UNKNOWN)
{
if ((dirent.flags & 3) == 2)
if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR)
type = GRUB_FSHELP_DIR;
else
type = GRUB_FSHELP_REG;
@ -678,7 +733,10 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
/* . and .. */
if (dirent.namelen == 1 && (name[0] == 0 || name[0] == 1))
continue;
{
grub_free (node);
continue;
}
else
filename = name;
}
@ -689,7 +747,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
oldname = filename;
filename = grub_iso9660_convert_string
((grub_uint16_t *) oldname, dirent.namelen >> 1);
((grub_uint8_t *) oldname, dirent.namelen >> 1);
semicolon = grub_strrchr (filename, ';');
if (semicolon)
@ -701,7 +759,64 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
filename_alloc = 1;
}
node->dirent = dirent;
node->dirents[0] = dirent;
while (dirent.flags & FLAG_MORE_EXTENTS)
{
offset += dirent.len;
if (read_node (dir, offset, sizeof (dirent), (char *) &dirent))
{
if (filename_alloc)
grub_free (filename);
grub_free (node);
return 0;
}
if (node->have_dirents >= node->alloc_dirents)
{
struct grub_fshelp_node *new_node;
node->alloc_dirents *= 2;
new_node = grub_realloc (node,
sizeof (struct grub_fshelp_node)
+ ((node->alloc_dirents
- ARRAY_SIZE (node->dirents))
* sizeof (node->dirents[0])));
if (!new_node)
{
if (filename_alloc)
grub_free (filename);
grub_free (node);
return 0;
}
node = new_node;
}
node->dirents[node->have_dirents++] = dirent;
}
if (symlink)
{
if ((node->alloc_dirents - node->have_dirents)
* sizeof (node->dirents[0]) < grub_strlen (symlink) + 1)
{
struct grub_fshelp_node *new_node;
new_node = grub_realloc (node,
sizeof (struct grub_fshelp_node)
+ ((node->alloc_dirents
- ARRAY_SIZE (node->dirents))
* sizeof (node->dirents[0]))
+ grub_strlen (symlink) + 1);
if (!new_node)
{
if (filename_alloc)
grub_free (filename);
grub_free (node);
return 0;
}
node = new_node;
}
node->have_symlink = 1;
grub_strcpy (node->symlink
+ node->have_dirents * sizeof (node->dirents[0])
- sizeof (node->dirents), symlink);
grub_free (symlink);
}
if (hook (filename, type, node))
{
if (filename_alloc)
@ -738,7 +853,7 @@ grub_iso9660_dir (grub_device_t device, const char *path,
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = !!iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime);
info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime);
grub_free (node);
return hook (filename, &info);
@ -751,8 +866,10 @@ grub_iso9660_dir (grub_device_t device, const char *path,
goto fail;
rootnode.data = data;
rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector);
rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size);
rootnode.alloc_dirents = 0;
rootnode.have_dirents = 1;
rootnode.have_symlink = 0;
rootnode.dirents[0] = data->voldesc.rootdir;
/* Use the fshelp function to traverse the path. */
if (grub_fshelp_find_file (path, &rootnode,
@ -792,8 +909,10 @@ grub_iso9660_open (struct grub_file *file, const char *name)
goto fail;
rootnode.data = data;
rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector);
rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size);
rootnode.alloc_dirents = 0;
rootnode.have_dirents = 1;
rootnode.have_symlink = 0;
rootnode.dirents[0] = data->voldesc.rootdir;
/* Use the fshelp function to traverse the path. */
if (grub_fshelp_find_file (name, &rootnode,
@ -803,10 +922,9 @@ grub_iso9660_open (struct grub_file *file, const char *name)
GRUB_FSHELP_REG))
goto fail;
data->first_sector = foundnode->blk;
data->node = foundnode;
file->data = data;
file->size = foundnode->size;
file->size = get_node_size (foundnode);
file->offset = 0;
return 0;
@ -828,10 +946,7 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len)
/* XXX: The file is stored in as a single extent. */
data->disk->read_hook = file->read_hook;
grub_disk_read (data->disk,
data->first_sector << GRUB_ISO9660_LOG2_BLKSZ,
file->offset,
len, buf);
read_node (data->node, file->offset, len, buf);
data->disk->read_hook = NULL;
if (grub_errno)
@ -844,7 +959,10 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len)
static grub_err_t
grub_iso9660_close (grub_file_t file)
{
grub_free (file->data);
struct grub_iso9660_data *data =
(struct grub_iso9660_data *) file->data;
grub_free (data->node);
grub_free (data);
grub_dl_unref (my_mod);
@ -861,8 +979,7 @@ grub_iso9660_label (grub_device_t device, char **label)
if (data)
{
if (data->joliet)
*label = grub_iso9660_convert_string
((grub_uint16_t *) &data->voldesc.volname, 16);
*label = grub_iso9660_convert_string (data->voldesc.volname, 16);
else
*label = grub_strndup ((char *) data->voldesc.volname, 32);
if (*label)

View file

@ -52,10 +52,11 @@ struct grub_jfs_sblock
grub_uint32_t blksz;
grub_uint16_t log2_blksz;
grub_uint8_t unused[71];
grub_uint8_t volname[11];
grub_uint8_t unused2[32];
grub_uint8_t unused[79];
char volname[11];
grub_uint8_t unused2[24];
grub_uint8_t uuid[16];
char volname2[16];
};
struct grub_jfs_extent
@ -205,7 +206,7 @@ struct grub_jfs_inode
struct
{
grub_uint8_t unused[32];
grub_uint8_t path[128];
grub_uint8_t path[256];
} symlink;
} __attribute__ ((packed));
} __attribute__ ((packed));
@ -238,7 +239,10 @@ struct grub_jfs_diropen
struct grub_jfs_leaf_next_dirent *next_leaf;
/* The filename and inode of the last read dirent. */
char name[255];
/* On-disk name is at most 255 UTF-16 codepoints.
Every UTF-16 codepoint is at most 4 UTF-8 bytes.
*/
char name[256 * GRUB_MAX_UTF8_PER_UTF16 + 1];
grub_uint32_t ino;
} __attribute__ ((packed));
@ -253,11 +257,11 @@ static grub_int64_t
grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
grub_uint64_t blk)
{
auto int getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents);
auto grub_int64_t getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents);
int getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents)
grub_int64_t getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents)
{
int found = -1;
int i;
@ -269,7 +273,7 @@ grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
/* Read the leafnode. */
if (grub_le_to_cpu32 (extents[i].offset2) <= blk
&& ((grub_le_to_cpu16 (extents[i].extent.length))
+ (extents[i].extent.length2 << 8)
+ (extents[i].extent.length2 << 16)
+ grub_le_to_cpu32 (extents[i].offset2)) > blk)
return (blk - grub_le_to_cpu32 (extents[i].offset2)
+ grub_le_to_cpu32 (extents[i].extent.blk2));
@ -288,7 +292,7 @@ grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
} tree;
if (grub_disk_read (data->disk,
grub_le_to_cpu32 (extents[found].extent.blk2)
((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2))
<< (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS), 0,
sizeof (tree), (char *) &tree))
@ -479,7 +483,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro)
struct grub_jfs_leaf_next_dirent *next_leaf;
int len;
int nextent;
grub_uint16_t filename[255];
grub_uint16_t filename[256];
auto void addstr (grub_uint16_t *uname, int ulen);
@ -487,7 +491,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro)
void addstr (grub_uint16_t *name, int ulen)
{
while (ulen--)
filename[strpos++] = *(name++);
filename[strpos++] = grub_le_to_cpu16 (*(name++));
}
/* The last node, read in more. */
@ -558,10 +562,10 @@ static grub_ssize_t
grub_jfs_read_file (struct grub_jfs_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
grub_uint64_t pos, grub_size_t len, char *buf)
grub_off_t pos, grub_size_t len, char *buf)
{
grub_uint64_t i;
grub_uint64_t blockcnt;
grub_off_t i;
grub_off_t blockcnt;
blockcnt = (len + pos + grub_le_to_cpu32 (data->sblock.blksz) - 1)
>> grub_le_to_cpu16 (data->sblock.log2_blksz);
@ -708,14 +712,14 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path,
static grub_err_t
grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino)
{
grub_uint64_t size = grub_le_to_cpu64 (data->currinode.size);
grub_size_t size = grub_le_to_cpu64 (data->currinode.size);
char symlink[size + 1];
if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT)
return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
if (size <= 128)
grub_strncpy (symlink, (char *) (data->currinode.symlink.path), 128);
if (size <= sizeof (data->currinode.symlink.path))
grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size);
else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0)
return grub_errno;
@ -884,10 +888,19 @@ grub_jfs_label (grub_device_t device, char **label)
data = grub_jfs_mount (device->disk);
if (data)
*label = grub_strndup ((char *) (data->sblock.volname), 11);
{
if (data->sblock.volname2[0])
*label = grub_strndup (data->sblock.volname2,
sizeof (data->sblock.volname2));
else
*label = grub_strndup (data->sblock.volname,
sizeof (data->sblock.volname));
}
else
*label = 0;
grub_free (data);
return grub_errno;
}

View file

@ -63,7 +63,7 @@ typedef grub_uint16_t grub_minix_ino_t;
#define grub_minix_le_to_cpu_ino grub_le_to_cpu16
#endif
#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size))
#define GRUB_MINIX_INODE_SIZE(data) (grub_le_to_cpu32 (data->inode.size))
#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode))
#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \
(data->inode.dir_zones[blk]))
@ -76,11 +76,11 @@ typedef grub_uint16_t grub_minix_ino_t;
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
+ grub_le_to_cpu16 (data->sblock.log2_zone_size))
#endif
#define GRUB_MINIX_ZONESZ (data->block_size \
<< grub_le_to_cpu16 (data->sblock.log2_zone_size))
#define GRUB_MINIX_ZONESZ (1 << (data->log_block_size \
+ grub_le_to_cpu16 (data->sblock.log2_zone_size)))
#ifdef MODE_MINIX3
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * (data->block_size / GRUB_DISK_SECTOR_SIZE))
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << (data->log_block_size - GRUB_DISK_SECTOR_BITS))
#else
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ)
#endif
@ -132,16 +132,15 @@ struct grub_minix_inode
grub_uint32_t dir_zones[7];
grub_uint32_t indir_zone;
grub_uint32_t double_indir_zone;
grub_uint32_t unused;
grub_uint32_t triple_indir_zone;
};
#else
struct grub_minix_inode
{
grub_uint16_t mode;
grub_uint16_t uid;
grub_uint16_t size;
grub_uint32_t ctime;
grub_uint32_t size;
grub_uint32_t mtime;
grub_uint8_t gid;
grub_uint8_t nlinks;
grub_uint16_t dir_zones[7];
@ -160,7 +159,7 @@ struct grub_minix_data
int linknest;
grub_disk_t disk;
int filename_size;
grub_size_t block_size;
grub_size_t log_block_size;
};
static grub_dl_t my_mod;
@ -168,15 +167,19 @@ static grub_dl_t my_mod;
static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
const char *path);
static int
static grub_minix_uintn_t
grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
{
int indir;
grub_minix_uintn_t indir;
const grub_uint32_t block_per_zone = (GRUB_MINIX_ZONESZ
/ GRUB_MINIX_INODE_BLKSZ (data));
auto int grub_get_indir (int, int);
auto grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t,
grub_minix_uintn_t);
/* Read the block pointer in ZONE, on the offset NUM. */
int grub_get_indir (int zone, int num)
grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t zone,
grub_minix_uintn_t num)
{
grub_minix_uintn_t indirn;
grub_disk_read (data->disk,
@ -192,25 +195,38 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
/* Indirect block. */
blk -= GRUB_MINIX_INODE_DIR_BLOCKS;
if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
if (blk < block_per_zone)
{
indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
return indir;
}
/* Double indirect block. */
blk -= GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data);
if (blk < (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
* (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)))
blk -= block_per_zone;
if (blk < block_per_zone * block_per_zone)
{
indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data),
blk / GRUB_MINIX_ZONESZ);
blk / block_per_zone);
indir = grub_get_indir (indir, blk % GRUB_MINIX_ZONESZ);
indir = grub_get_indir (indir, blk % block_per_zone);
return indir;
}
#if defined (MODE_MINIX3) || defined (MODE_MINIX2)
blk -= block_per_zone * block_per_zone;
if (blk < ((grub_uint64_t) block_per_zone * (grub_uint64_t) block_per_zone
* (grub_uint64_t) block_per_zone))
{
indir = grub_get_indir (grub_minix_le_to_cpu_n (data->inode.triple_indir_zone),
(blk / block_per_zone) / block_per_zone);
indir = grub_get_indir (indir, (blk / block_per_zone) % block_per_zone);
indir = grub_get_indir (indir, blk % block_per_zone);
return indir;
}
#endif
/* This should never happen. */
grub_error (GRUB_ERR_OUT_OF_RANGE, "file bigger than maximum size");
@ -235,14 +251,15 @@ grub_minix_read_file (struct grub_minix_data *data,
if (len + pos > GRUB_MINIX_INODE_SIZE (data))
len = GRUB_MINIX_INODE_SIZE (data) - pos;
blockcnt = grub_divmod64 ((len + pos + data->block_size - 1),
data->block_size, 0);
posblock = grub_divmod64 (pos, data->block_size, &blockoff);
blockcnt = ((len + pos + (1 << data->log_block_size) - 1)
>> data->log_block_size);
posblock = pos >> data->log_block_size;
blockoff = pos & ((1 << data->log_block_size) - 1);
for (i = posblock; i < blockcnt; i++)
{
grub_disk_addr_t blknr;
grub_uint64_t blockend = data->block_size;
grub_uint64_t blockend = 1 << data->log_block_size;
grub_off_t skipfirst = 0;
blknr = grub_minix_get_file_block (data, i);
@ -252,10 +269,10 @@ grub_minix_read_file (struct grub_minix_data *data,
/* Last block. */
if (i == blockcnt - 1)
{
grub_divmod64 (len + pos, data->block_size, &blockend);
blockend = (len + pos) & ((1 << data->log_block_size) - 1);
if (!blockend)
blockend = data->block_size;
blockend = 1 << data->log_block_size;
}
/* First block. */
@ -273,7 +290,7 @@ grub_minix_read_file (struct grub_minix_data *data,
if (grub_errno)
return -1;
buf += data->block_size - skipfirst;
buf += (1 << data->log_block_size) - skipfirst;
}
return len;
@ -463,9 +480,20 @@ grub_minix_mount (grub_disk_t disk)
data->disk = disk;
data->linknest = 0;
#ifdef MODE_MINIX3
data->block_size = grub_le_to_cpu16 (data->sblock.block_size);
/* These tests are endian-independent. No need to byteswap. */
if (data->sblock.block_size == 0xffff)
data->log_block_size = 10;
else
{
if ((data->sblock.block_size & (data->sblock.block_size - 1))
|| data->sblock.block_size == 0)
goto fail;
for (data->log_block_size = 0; (1 << data->log_block_size)
< grub_le_to_cpu16 (data->sblock.block_size);
data->log_block_size++);
}
#else
data->block_size = 1024U;
data->log_block_size = 10;
#endif
return data;
@ -536,11 +564,7 @@ grub_minix_dir (grub_device_t device, const char *path,
info.dir = ((GRUB_MINIX_INODE_MODE (data)
& GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
info.mtimeset = 1;
#ifndef MODE_MINIX2
info.mtime = grub_le_to_cpu32 (data->inode.ctime);
#else
info.mtime = grub_le_to_cpu32 (data->inode.mtime);
#endif
if (hook (filename, &info) ? 1 : 0)
break;

2
grub-core/fs/newc.c Normal file
View file

@ -0,0 +1,2 @@
#define MODE_NEWC 1
#include "cpio.c"

View file

@ -49,7 +49,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
/* nilfs btree node level. */
#define NILFS_BTREE_LEVEL_DATA 0
#define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1)
#define NILFS_BTREE_LEVEL_MAX 14
/* nilfs 1st super block posission from beginning of the partition
in 512 block size */
@ -58,6 +57,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
in 512 block size */
#define NILFS_2ND_SUPER_BLOCK(devsize) (((devsize >> 3) - 1) << 3)
#define LOG_INODE_SIZE 7
struct grub_nilfs2_inode
{
grub_uint64_t i_blocks;
@ -126,8 +126,7 @@ struct grub_nilfs2_super_block
grub_uint16_t s_checkpoint_size;
grub_uint16_t s_segment_usage_size;
grub_uint8_t s_uuid[16];
char s_volume_name[16];
char s_last_mounted[64];
char s_volume_name[80];
grub_uint32_t s_c_interval;
grub_uint32_t s_c_block_max;
grub_uint32_t s_reserved[192];
@ -207,6 +206,7 @@ struct grub_nilfs2_btree_node
grub_uint8_t bn_level;
grub_uint16_t bn_nchildren;
grub_uint32_t bn_pad;
grub_uint64_t keys[0];
};
struct grub_nilfs2_palloc_group_desc
@ -214,6 +214,7 @@ struct grub_nilfs2_palloc_group_desc
grub_uint32_t pg_nfrees;
};
#define LOG_NILFS_DAT_ENTRY_SIZE 5
struct grub_nilfs2_dat_entry
{
grub_uint64_t de_blocknr;
@ -296,17 +297,17 @@ static grub_dl_t my_mod;
static inline unsigned long
grub_nilfs2_palloc_entries_per_group (struct grub_nilfs2_data *data)
grub_nilfs2_log_palloc_entries_per_group (struct grub_nilfs2_data *data)
{
return 1UL << (LOG2_BLOCK_SIZE (data) + 3);
return LOG2_BLOCK_SIZE (data) + 3;
}
static inline grub_uint64_t
grub_nilfs2_palloc_group (struct grub_nilfs2_data *data,
grub_uint64_t nr, grub_uint64_t * offset)
{
return grub_divmod64 (nr, grub_nilfs2_palloc_entries_per_group (data),
offset);
*offset = nr & ((1 << grub_nilfs2_log_palloc_entries_per_group (data)) - 1);
return nr >> grub_nilfs2_log_palloc_entries_per_group (data);
}
static inline grub_uint32_t
@ -317,55 +318,58 @@ grub_nilfs2_palloc_groups_per_desc_block (struct grub_nilfs2_data *data)
}
static inline grub_uint32_t
grub_nilfs2_entries_per_block (struct grub_nilfs2_data *data,
unsigned long entry_size)
grub_nilfs2_log_entries_per_block_log (struct grub_nilfs2_data *data,
unsigned long log_entry_size)
{
return NILFS2_BLOCK_SIZE (data) / entry_size;
return LOG2_BLOCK_SIZE (data) - log_entry_size;
}
static inline grub_uint32_t
grub_nilfs2_blocks_per_group (struct grub_nilfs2_data *data,
unsigned long entry_size)
grub_nilfs2_blocks_per_group_log (struct grub_nilfs2_data *data,
unsigned long log_entry_size)
{
return grub_div_roundup (grub_nilfs2_palloc_entries_per_group (data),
grub_nilfs2_entries_per_block (data,
entry_size)) + 1;
return (1 << (grub_nilfs2_log_palloc_entries_per_group (data)
- grub_nilfs2_log_entries_per_block_log (data,
log_entry_size))) + 1;
}
static inline grub_uint32_t
grub_nilfs2_blocks_per_desc_block (struct grub_nilfs2_data *data,
unsigned long entry_size)
grub_nilfs2_blocks_per_desc_block_log (struct grub_nilfs2_data *data,
unsigned long log_entry_size)
{
return grub_nilfs2_palloc_groups_per_desc_block (data) *
grub_nilfs2_blocks_per_group (data, entry_size) + 1;
grub_nilfs2_blocks_per_group_log (data, log_entry_size) + 1;
}
static inline grub_uint32_t
grub_nilfs2_palloc_desc_block_offset (struct grub_nilfs2_data *data,
unsigned long group,
unsigned long entry_size)
grub_nilfs2_palloc_desc_block_offset_log (struct grub_nilfs2_data *data,
unsigned long group,
unsigned long log_entry_size)
{
grub_uint32_t desc_block =
group / grub_nilfs2_palloc_groups_per_desc_block (data);
return desc_block * grub_nilfs2_blocks_per_desc_block (data, entry_size);
return desc_block * grub_nilfs2_blocks_per_desc_block_log (data,
log_entry_size);
}
static inline grub_uint32_t
grub_nilfs2_palloc_bitmap_block_offset (struct grub_nilfs2_data *data,
unsigned long group,
unsigned long entry_size)
unsigned long log_entry_size)
{
unsigned long desc_offset = group %
grub_nilfs2_palloc_groups_per_desc_block (data);
return grub_nilfs2_palloc_desc_block_offset (data, group, entry_size) + 1 +
desc_offset * grub_nilfs2_blocks_per_group (data, entry_size);
return grub_nilfs2_palloc_desc_block_offset_log (data, group, log_entry_size)
+ 1
+ desc_offset * grub_nilfs2_blocks_per_group_log (data, log_entry_size);
}
static inline grub_uint32_t
grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data,
grub_uint64_t nr, unsigned long entry_size)
grub_nilfs2_palloc_entry_offset_log (struct grub_nilfs2_data *data,
grub_uint64_t nr,
unsigned long log_entry_size)
{
unsigned long group;
grub_uint64_t group_offset;
@ -373,10 +377,9 @@ grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data,
group = grub_nilfs2_palloc_group (data, nr, &group_offset);
return grub_nilfs2_palloc_bitmap_block_offset (data, group,
entry_size) + 1 +
grub_divmod64 (group_offset, grub_nilfs2_entries_per_block (data,
entry_size),
NULL);
1 << log_entry_size) + 1 +
(group_offset >> grub_nilfs2_log_entries_per_block_log (data,
log_entry_size));
}
@ -395,9 +398,9 @@ grub_nilfs2_btree_get_level (struct grub_nilfs2_btree_node *node)
static inline grub_uint64_t *
grub_nilfs2_btree_node_dkeys (struct grub_nilfs2_btree_node *node)
{
return (grub_uint64_t *) ((char *) (node + 1) +
((node->bn_flags & NILFS_BTREE_NODE_ROOT) ?
0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
return (node->keys +
((node->bn_flags & NILFS_BTREE_NODE_ROOT) ?
0 : (NILFS_BTREE_NODE_EXTRA_PAD_SIZE / sizeof (grub_uint64_t))));
}
static inline grub_uint64_t
@ -498,7 +501,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
grub_uint64_t key, int need_translate)
{
struct grub_nilfs2_btree_node *node;
unsigned char block[NILFS2_BLOCK_SIZE (data)];
GRUB_PROPERLY_ALIGNED_ARRAY (block, NILFS2_BLOCK_SIZE (data));
grub_uint64_t ptr;
int level, found, index;
@ -582,12 +585,11 @@ grub_nilfs2_dat_translate (struct grub_nilfs2_data *data, grub_uint64_t key)
grub_uint64_t blockno, offset;
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
blockno = grub_nilfs2_palloc_entry_offset (data, key,
sizeof (struct
grub_nilfs2_dat_entry));
blockno = grub_nilfs2_palloc_entry_offset_log (data, key,
LOG_NILFS_DAT_ENTRY_SIZE);
grub_divmod64 (key * sizeof (struct grub_nilfs2_dat_entry),
NILFS2_BLOCK_SIZE (data), &offset);
offset = ((key * sizeof (struct grub_nilfs2_dat_entry))
& ((1 << LOG2_BLOCK_SIZE (data)) - 1));
pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_dat, blockno, 0);
if (pptr == (grub_uint64_t) - 1)
@ -628,7 +630,7 @@ grub_nilfs2_read_file (grub_fshelp_node_t node,
sector,
unsigned offset,
unsigned length),
int pos, grub_size_t len, char *buf)
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_nilfs2_read_block,
@ -652,8 +654,8 @@ grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data,
sizeof(struct grub_nilfs2_checkpoint).
*/
blockno = grub_divmod64 (cpno, NILFS2_BLOCK_SIZE (data) /
sizeof (struct grub_nilfs2_checkpoint), &offset);
sizeof (struct grub_nilfs2_checkpoint), &offset);
pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_cpfile, blockno, 1);
if (pptr == (grub_uint64_t) - 1)
{
@ -686,12 +688,11 @@ grub_nilfs2_read_inode (struct grub_nilfs2_data *data,
grub_disk_t disk = data->disk;
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
blockno = grub_nilfs2_palloc_entry_offset (data, ino,
sizeof (struct
grub_nilfs2_inode));
blockno = grub_nilfs2_palloc_entry_offset_log (data, ino,
LOG_INODE_SIZE);
grub_divmod64 (sizeof (struct grub_nilfs2_inode) * ino,
NILFS2_BLOCK_SIZE (data), &offset);
offset = ((sizeof (struct grub_nilfs2_inode) * ino)
& ((1 << LOG2_BLOCK_SIZE (data)) - 1));
pptr = grub_nilfs2_bmap_lookup (data, &data->ifile, blockno, 1);
if (pptr == (grub_uint64_t) - 1)
{
@ -732,7 +733,11 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data)
/* Make sure if 1st super block is valid. */
valid[0] = grub_nilfs2_valid_sb (&data->sblock);
partition_size = grub_disk_get_size (disk);
if (valid[0])
partition_size = (grub_le_to_cpu64 (data->sblock.s_dev_size)
>> GRUB_DISK_SECTOR_BITS);
else
partition_size = grub_disk_get_size (disk);
if (partition_size != GRUB_DISK_SIZE_UNKNOWN)
{
/* Read second super block. */
@ -866,7 +871,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
unsigned int fpos = 0;
grub_off_t fpos = 0;
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
if (!diro->inode_read)
@ -1093,7 +1098,8 @@ grub_nilfs2_label (grub_device_t device, char **label)
data = grub_nilfs2_mount (disk);
if (data)
*label = grub_strndup (data->sblock.s_volume_name, 14);
*label = grub_strndup (data->sblock.s_volume_name,
sizeof (data->sblock.s_volume_name));
else
*label = NULL;
@ -1117,7 +1123,7 @@ grub_nilfs2_uuid (grub_device_t device, char **uuid)
{
*uuid =
grub_xasprintf
("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%0x-%02x%02x%02x%02x%02x%02x",
("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
data->sblock.s_uuid[0], data->sblock.s_uuid[1],
data->sblock.s_uuid[2], data->sblock.s_uuid[3],
data->sblock.s_uuid[4], data->sblock.s_uuid[5],
@ -1150,7 +1156,7 @@ grub_nilfs2_mtime (grub_device_t device, grub_int32_t * tm)
if (!data)
*tm = 0;
else
*tm = (grub_int32_t) grub_le_to_cpu64 (data->sblock.s_mtime);
*tm = (grub_int32_t) grub_le_to_cpu64 (data->sblock.s_wtime);
grub_dl_unref (my_mod);
@ -1178,6 +1184,11 @@ static struct grub_fs grub_nilfs2_fs = {
GRUB_MOD_INIT (nilfs2)
{
COMPILE_TIME_ASSERT ((1 << LOG_NILFS_DAT_ENTRY_SIZE)
== sizeof (struct
grub_nilfs2_dat_entry));
COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
== sizeof (struct grub_nilfs2_inode));
grub_fs_register (&grub_nilfs2_fs);
my_mod = mod;
}

Some files were not shown because too many files have changed in this diff Show more