diff options
author | BlackNoxis <steven.darklight@gmail.com> | 2014-02-15 23:24:26 +0200 |
---|---|---|
committer | BlackNoxis <steven.darklight@gmail.com> | 2014-02-15 23:24:26 +0200 |
commit | 7224c1253228e5c29c78cb3f0f26ce34770f2356 (patch) | |
tree | 1684924656132935256e034f35f92abee6623265 /sys-boot/grub/files |
Added ebuilds for kogaion desktop
Diffstat (limited to 'sys-boot/grub/files')
62 files changed, 11911 insertions, 0 deletions
diff --git a/sys-boot/grub/files/00_fonts b/sys-boot/grub/files/00_fonts new file mode 100755 index 00000000..6f5d98b5 --- /dev/null +++ b/sys-boot/grub/files/00_fonts @@ -0,0 +1,14 @@ +# Create required fonts, otherwise graphic mode won't be loaded +if [ -x "/usr/bin/grub2-mkfont" ]; then + # This is the bare minimum + /usr/bin/grub2-mkfont --output=/boot/grub/unifont.pf2 \ + /usr/share/fonts/unifont/unifont.pcf.gz + + # let's load DejaVu if exists, no deps against it + # to avoid crazy deps on critical pkg + if [ -x "/usr/share/fonts/dejavu/DejaVuSans.ttf" ]; then + /usr/bin/grub2-mkfont --output=/boot/grub/dejavu.pf2 \ + /usr/share/fonts/dejavu/DejaVuSans.ttf + fi + +fi diff --git a/sys-boot/grub/files/05_distro_theme b/sys-boot/grub/files/05_distro_theme new file mode 100755 index 00000000..cb4c197c --- /dev/null +++ b/sys-boot/grub/files/05_distro_theme @@ -0,0 +1,51 @@ +#!/bin/bash -e + +. /lib/grub/grub-mkconfig_lib + +set_blue_theme() +{ + cat << EOF +set menu_color_normal=cyan/blue +set menu_color_highlight=white/blue +EOF +} + +# check for usable backgrounds +use_bg=false +if [ "$GRUB_TERMINAL_OUTPUT" = "gfxterm" ] && [ -n "${GRUB_WALLPAPER}" ]; then + for i in /boot/grub/`basename ${GRUB_WALLPAPER}` ${GRUB_WALLPAPER} ; do + if is_path_readable_by_grub $i ; then + bg=$i + case ${bg} in + *.png) reader=png ;; + *.tga) reader=tga ;; + *.jpg|*.jpeg) reader=jpeg ;; + esac + if test -e /boot/grub/${reader}.mod ; then + echo "Found background image: `basename ${bg}`" >&2 + use_bg=true + break + fi + fi + done +fi + +# set the background if possible +if ${use_bg} ; then + prepare_grub_to_access_device `${grub_probe} --target=device ${bg}` + cat << EOF +insmod ${reader} +if background_image `make_system_path_relative_to_its_root ${bg}` ; then + set color_normal=${GRUB_COLOR_NORMAL} + set color_highlight=${GRUB_COLOR_HIGHLIGHT} +else +EOF +fi + +# otherwise, set the traditional Debian blue theme +if ${use_bg} ; then + set_blue_theme | sed -e "s/^/ /g" + echo "fi" +else + set_blue_theme +fi diff --git a/sys-boot/grub/files/grub-0.97-gfxmenu-v8.patch b/sys-boot/grub/files/grub-0.97-gfxmenu-v8.patch new file mode 100644 index 00000000..7921fc82 --- /dev/null +++ b/sys-boot/grub/files/grub-0.97-gfxmenu-v8.patch @@ -0,0 +1,1003 @@ +diff -Nurp grub-0.97.orig/docs/grub.texi grub-0.97/docs/grub.texi +--- grub-0.97.orig/docs/grub.texi 2009-08-03 16:25:36.636294219 +0200 ++++ grub-0.97/docs/grub.texi 2009-08-03 16:25:52.207398764 +0200 +@@ -2118,6 +2118,7 @@ These commands can only be used in the m + * default:: Set the default entry + * fallback:: Set the fallback entry + * hiddenmenu:: Hide the menu interface ++* gfxmenu:: Use graphical menu interface + * timeout:: Set the timeout + * title:: Start a menu entry + @end menu +@@ -2150,6 +2151,15 @@ fallback entry numbers. + @end deffn + + ++@node gfxmenu ++@subsection gfxmenu ++ ++@deffn Command gfxmenu file ++Use the graphical menu interface. The graphics data are taken from ++@var{file} and must be created using 'mkbootmsg' from the gfxboot package. ++@end deffn ++ ++ + @node hiddenmenu + @subsection hiddenmenu + +diff -Nurp grub-0.97.orig/grub/asmstub.c grub-0.97/grub/asmstub.c +--- grub-0.97.orig/grub/asmstub.c 2009-08-03 16:25:36.483169221 +0200 ++++ grub-0.97/grub/asmstub.c 2009-08-03 16:25:52.217342924 +0200 +@@ -480,6 +480,32 @@ set_vbe_mode (int mode_number) + return 0; + } + ++/* graphical menu functions . */ ++int ++gfx_init (gfx_data_t *gfx_data) ++{ ++ return 0; ++} ++ ++int ++gfx_done (gfx_data_t *gfx_data) ++{ ++ return 0; ++} ++ ++int ++gfx_input (gfx_data_t *gfx_data, int *menu_entry) ++{ ++ return 0; ++} ++ ++int ++gfx_setup_menu (gfx_data_t *gfx_data) ++{ ++ return 0; ++} ++ ++ + /* low-level timing info */ + int + getrtsecs (void) +diff -Nurp grub-0.97.orig/stage2/asm.S grub-0.97/stage2/asm.S +--- grub-0.97.orig/stage2/asm.S 2004-06-19 18:55:22.000000000 +0200 ++++ grub-0.97/stage2/asm.S 2009-08-03 16:25:52.218406926 +0200 +@@ -1610,6 +1610,286 @@ ENTRY(set_vbe_mode) + popl %ebp + ret + ++ ++/* ++ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ * ++ * graphical menu functions ++ * ++ */ ++ ++/* ++ * int gfx_init (gfx_data_t *gfx_data) ++ * ++ * init gfx things ++ * ++ * return vales: ++ * 0: ok ++ * 1: failed ++ * sets gfx_data->ok ++ */ ++ ++ENTRY(gfx_init) ++ pushl %ebp ++ movl %esp, %ebp ++ ++ pushl %edi ++ pushl %esi ++ pushl %ebx ++ ++ movl 8(%ebp),%edx ++ movl %edx,%edi ++ leal gfx_ofs_sys_cfg(%edx),%esi ++ andl $0xf,%edi ++ shrl $4,%edx ++ ++ pushl %ebp ++ ++ call EXT_C(prot_to_real) ++ .code16 ++ ++ pushw %ds ++ movw %dx,%ds ++ ++ lcall *gfx_ofs_jmp_table + 4 * 0 (%di) ++ ++ sbbl %ebx,%ebx ++ negl %ebx ++ ++ popw %ds ++ ++ DATA32 call EXT_C(real_to_prot) ++ .code32 ++ ++ popl %ebp ++ ++ movl %ebx,%eax ++ xorl $1,%ebx ++ movl 8(%ebp),%edx ++ movl %ebx,gfx_ofs_ok(%edx) ++ ++ popl %ebx ++ popl %esi ++ popl %edi ++ ++ popl %ebp ++ ret ++ ++ ++/* ++ * int gfx_done (gfx_data_t *gfx_data) ++ * ++ * shut down gfx things ++ * ++ * return vales: ++ * always 0 ++ * sets gfx_data->ok ++ */ ++ ++ENTRY(gfx_done) ++ pushl %ebp ++ movl %esp, %ebp ++ ++ pushl %edi ++ pushl %esi ++ pushl %ebx ++ ++ movl 8(%ebp),%edx ++ movl %edx,%ebx ++ andl $0xf,%ebx ++ shrl $4,%edx ++ ++ pushl %ebp ++ ++ call EXT_C(prot_to_real) ++ .code16 ++ ++ pushw %ds ++ ++ movw %dx,%ds ++ ++ lcall *gfx_ofs_jmp_table + 4 * 1 (%bx) ++ ++ popw %ds ++ ++ DATA32 call EXT_C(real_to_prot) ++ .code32 ++ ++ popl %ebp ++ ++ xorl %eax,%eax ++ movl 8(%ebp),%edx ++ movl %eax,gfx_ofs_ok(%edx) ++ ++ popl %ebx ++ popl %esi ++ popl %edi ++ ++ popl %ebp ++ ret ++ ++ ++/* ++ * int gfx_input (gfx_data_t *gfx_data, int *menu_entry) ++ * ++ * let user enter a command line ++ * ++ * uses gfx_data->cmdline as buffer ++ * ++ * return values: ++ * 1: abort ++ * 2: boot ++ * menu_entry: selected entry ++ */ ++ ++ENTRY(gfx_input) ++ pushl %ebp ++ movl %esp, %ebp ++ ++ pushl %edi ++ pushl %esi ++ pushl %ebx ++ ++ movl 8(%ebp),%edx ++ movl %edx,%ebx ++ leal gfx_ofs_sys_cfg(%edx),%esi ++ andl $0xf,%ebx ++ shrl $4,%edx ++ ++ pushl %ebp ++ ++ call EXT_C(prot_to_real) ++ .code16 ++ ++ pushw %ds ++ ++ movw %dx,%ds ++ ++ movl gfx_ofs_cmdline(%bx),%edi ++ movl gfx_ofs_cmdline_len(%bx),%ecx ++ movl gfx_ofs_timeout(%bx),%eax ++ imull $18,%eax ++ ++ lcall *gfx_ofs_jmp_table + 4 * 2 (%bx) ++ ++ movl %eax,%ecx ++ ++ popw %ds ++ ++ DATA32 call EXT_C(real_to_prot) ++ .code32 ++ ++ popl %ebp ++ ++ movl 12(%ebp),%edx ++ movl %ebx,(%edx) ++ ++ movl %ecx,%eax ++ ++ popl %ebx ++ popl %esi ++ popl %edi ++ ++ popl %ebp ++ ret ++ ++ ++/* ++ * int gfx_setup_menu (gfx_data_t *gfx_data) ++ * ++ * draw boot menu ++ * ++ * return values: ++ * always 0 ++ */ ++ ++/* menu entry descriptor */ ++#define menu_entries 0 ++#define menu_default 2 /* seg:ofs */ ++#define menu_ent_list 6 /* seg:ofs */ ++#define menu_ent_size 10 ++#define menu_arg_list 12 /* seg:ofs */ ++#define menu_arg_size 16 ++#define sizeof_menu_desc 18 ++ ++ENTRY(gfx_setup_menu) ++ pushl %ebp ++ movl %esp, %ebp ++ ++ pushl %edi ++ pushl %esi ++ pushl %ebx ++ ++ movl 8(%ebp),%edx ++ movl %edx,%ebx ++ andl $0xf,%ebx ++ shrl $4,%edx ++ ++ call EXT_C(prot_to_real) ++ .code16 ++ ++ pushw %ds ++ ++ movw %dx,%ds ++ shll $4,%edx ++ ++ subw $sizeof_menu_desc,%sp ++ movw %esp,%ebp ++ ++ movl gfx_ofs_menu_entries(%bx),%eax ++ movw %ax,menu_entries(%bp) ++ ++ movl gfx_ofs_menu_default_entry(%bx),%eax ++ subl %edx,%eax ++ movw %ax,menu_default(%bp) ++ movw %ds,menu_default+2(%bp) ++ ++ movl gfx_ofs_menu_list(%bx),%eax ++ subl %edx,%eax ++ movw %ax,menu_ent_list(%bp) ++ movw %ds,menu_ent_list+2(%bp) ++ ++ movl gfx_ofs_menu_entry_len(%bx),%eax ++ movw %ax,menu_ent_size(%bp) ++ ++ movl gfx_ofs_args_list(%bx),%eax ++ subl %edx,%eax ++ movw %ax,menu_arg_list(%bp) ++ movw %ds,menu_arg_list+2(%bp) ++ ++ movl gfx_ofs_args_entry_len(%bx),%eax ++ movw %ax,menu_arg_size(%bp) ++ ++ movl %ss,%esi ++ shll $4,%esi ++ addl %ebp,%esi ++ ++ lcall %ds: *gfx_ofs_jmp_table + 4 * 3 (%bx) ++ ++ addw $sizeof_menu_desc,%sp ++ ++ popw %ds ++ ++ DATA32 call EXT_C(real_to_prot) ++ .code32 ++ ++ xorl %eax,%eax ++ ++ popl %ebx ++ popl %esi ++ popl %edi ++ ++ popl %ebp ++ ret ++ ++ ++/* ++ * ++ * end graphics stuff ++ * ++ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ */ ++ + + /* + * gateA20(int linear) +diff -Nurp grub-0.97.orig/stage2/builtins.c grub-0.97/stage2/builtins.c +--- grub-0.97.orig/stage2/builtins.c 2009-08-03 16:25:36.601273171 +0200 ++++ grub-0.97/stage2/builtins.c 2009-08-03 16:25:52.219523396 +0200 +@@ -67,6 +67,8 @@ int fallback_entryno; + int fallback_entries[MAX_FALLBACK_ENTRIES]; + /* The number of current entry. */ + int current_entryno; ++/* graphics file */ ++char graphics_file[64]; + /* The address for Multiboot command-line buffer. */ + static char *mb_cmdline; + /* The password. */ +@@ -1335,6 +1337,26 @@ static struct builtin builtin_fstest = + }; + + ++/* graphics */ ++static int ++gfxmenu_func (char *arg, int flags) ++{ ++ memmove(graphics_file, arg, sizeof graphics_file - 1); ++ graphics_file[sizeof graphics_file - 1] = 0; ++ ++ return 0; ++} ++ ++static struct builtin builtin_gfxmenu = ++{ ++ "gfxmenu", ++ gfxmenu_func, ++ BUILTIN_MENU | BUILTIN_HELP_LIST, ++ "gfxmenu FILE", ++ "Use the graphical menu from FILE." ++}; ++ ++ + /* geometry */ + static int + geometry_func (char *arg, int flags) +@@ -4989,6 +5011,7 @@ struct builtin *builtin_table[] = + &builtin_find, + &builtin_fstest, + &builtin_geometry, ++ &builtin_gfxmenu, + &builtin_halt, + &builtin_help, + &builtin_hiddenmenu, +diff -Nurp grub-0.97.orig/stage2/shared.h grub-0.97/stage2/shared.h +--- grub-0.97.orig/stage2/shared.h 2004-06-19 18:40:09.000000000 +0200 ++++ grub-0.97/stage2/shared.h 2009-08-03 16:25:52.219523396 +0200 +@@ -374,6 +374,22 @@ extern char *grub_scratch_mem; + #endif /* WITHOUT_LIBC_STUBS */ + + ++/* see typedef gfx_data_t below */ ++#define gfx_ofs_ok 0x00 ++#define gfx_ofs_code_seg 0x04 ++#define gfx_ofs_jmp_table 0x08 ++#define gfx_ofs_sys_cfg 0x38 ++#define gfx_ofs_cmdline 0x6c ++#define gfx_ofs_cmdline_len 0x70 ++#define gfx_ofs_menu_list 0x74 ++#define gfx_ofs_menu_default_entry 0x78 ++#define gfx_ofs_menu_entries 0x7c ++#define gfx_ofs_menu_entry_len 0x80 ++#define gfx_ofs_args_list 0x84 ++#define gfx_ofs_args_entry_len 0x88 ++#define gfx_ofs_timeout 0x8c ++ ++ + #ifndef ASM_FILE + /* + * Below this should be ONLY defines and other constructs for C code. +@@ -595,6 +611,38 @@ extern int fallback_entryno; + extern int default_entry; + extern int current_entryno; + ++ ++/* ++ * graphics menu stuff ++ * ++ * Note: gfx_data and all data referred to in it must lie within a 64k area. ++ */ ++typedef struct { ++ unsigned ok; /* set while we're in graphics mode */ ++ unsigned code_seg; /* code segment of binary graphics code */ ++ unsigned jmp_table[12]; /* link to graphics functions */ ++ unsigned char sys_cfg[52]; /* sys_cfg[0]: identifies boot loader (grub == 2) */ ++ char *cmdline; /* command line returned by gfx_input() */ ++ unsigned cmdline_len; /* length of the above */ ++ char *menu_list; /* list of menu entries, each of fixed length (menu_entry_len) */ ++ char *menu_default_entry; /* the default entry */ ++ unsigned menu_entries; /* number of entries in menu_list */ ++ unsigned menu_entry_len; /* one entry */ ++ char *args_list; /* same structure as menu_list, menu_entries entries */ ++ unsigned args_entry_len; /* one entry */ ++ unsigned timeout; /* in seconds (0: no timeout) */ ++} __attribute__ ((packed)) gfx_data_t; ++ ++extern gfx_data_t *graphics_data; ++ ++/* pointer to graphics image data */ ++extern char graphics_file[64]; ++ ++int gfx_init(gfx_data_t *gfx_data); ++int gfx_done(gfx_data_t *gfx_data); ++int gfx_input(gfx_data_t *gfx_data, int *menu_entry); ++int gfx_setup_menu(gfx_data_t *gfx_data); ++ + /* The constants for password types. */ + typedef enum + { +diff -Nurp grub-0.97.orig/stage2/stage2.c grub-0.97/stage2/stage2.c +--- grub-0.97.orig/stage2/stage2.c 2005-03-19 18:51:57.000000000 +0100 ++++ grub-0.97/stage2/stage2.c 2009-08-03 16:25:52.220523160 +0200 +@@ -22,6 +22,8 @@ + + grub_jmp_buf restart_env; + ++gfx_data_t *graphics_data; ++ + #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS) + + # if defined(PRESET_MENU_STRING) +@@ -310,6 +312,12 @@ restart: + + if (! auth && password) + { ++ if (*graphics_file) ++ { ++ printf ("\ ++ WARNING: graphical menu doesn\'t work\ ++ in conjunction with the password feature\n" ); ++ } + printf ("\ + Press enter to boot the selected OS or \'p\' to enter a\n\ + password to unlock the next set of features."); +@@ -753,6 +761,496 @@ restart: + } + + ++ ++#if 0 ++/* for debugging */ ++static void hexdump(unsigned char *buf, unsigned len) ++{ ++ int i, j = 0; ++ char s[17]; ++ unsigned addr = (unsigned) buf; ++ ++ s[16] = 0; ++ while(len--) { ++ i = buf[j]; ++ i = i & 0xff; ++ s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.'; ++ if(!(j & 15)) { ++ printf("%x ", j + addr); ++ } ++ if(!(j & 7) && (j & 15)) printf(" "); ++ /* stupid grub_printf */ ++ printf("%x", (i >> 4) & 0x0f); ++ printf("%x ", i & 0x0f); ++ if(!(++j & 15)) { ++ printf(" %s\n", s); ++ } ++ } ++ ++ if(j & 15) { ++ s[j & 15] = 0; ++ if(!(j & 8)) printf(" "); ++ i = 1 + 3 * (16 - (j & 15)); ++ while(i--) printf(" "); ++ printf("%s\n", s); ++ } ++} ++#endif ++ ++ ++/* kernel + (grub-)module options */ ++#define GFX_CMD_BUF_SIZE 512 ++ ++/* command line separator char */ ++#define GFX_CMD_SEP 1 ++ ++/* ++ * Go through config entry and find kernel args, if any. ++ * Put things into buf and return it. ++ */ ++static char *get_kernel_args(char *cfg, char *buf) ++{ ++ int i, j; ++ char *s, *t = "", *p, *t2; ++ ++ *(p = buf) = 0; ++ ++ for(j = 0; ; j++) { ++ s = get_entry(cfg, j, 0); ++ if(!*s) break; ++ if( ++ (!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) && ++ (s[6] == ' ' || s[6] == '\t') ++ ) { ++ t = skip_to(0, s); ++ t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL; ++ if(*t) t = skip_to(0, t); ++ if(t2 && t2 < t) break; /* module is likely a normal initrd -> skip */ ++ i = strlen(t); ++ if(p - buf + i > GFX_CMD_BUF_SIZE - 2) break; ++ *p++ = GFX_CMD_SEP; ++ strcpy(p, t); ++ p += i; ++ ++ continue; ++ } ++ } ++ ++ if(*buf) buf++; /* skip initial separator char */ ++ ++ return buf; ++} ++ ++ ++/* ++ * Check header and return code start offset. ++ */ ++static unsigned magic_ok(unsigned char *buf) ++{ ++ if( ++ *(unsigned *) buf == 0x0b2d97f00 && /* magic id */ ++ (buf[4] == 8) /* version 8 */ ++ ) { ++ return *(unsigned *) (buf + 8); ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * Search cpio archive for gfx file. ++ */ ++static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len) ++{ ++ unsigned i, fname_len, code_start = 0; ++ ++ *gfx_file_start = 0; ++ ++ for(i = 0; i < len;) { ++ if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) { ++ fname_len = *(unsigned short *) (buf + i + 20); ++ *file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16); ++ i += 26 + fname_len; ++ i = ((i + 1) & ~1); ++ if((code_start = magic_ok(buf + i))) { ++ *gfx_file_start = i; ++ return code_start; ++ } ++ i += *file_len; ++ i = ((i + 1) & ~1); ++ } ++ else { ++ break; ++ } ++ } ++ ++ return code_start; ++} ++ ++static inline unsigned char * stack_ptr(void) ++{ ++ unsigned char * u; ++ ++ asm("movl %%esp, %0" : "=r" (u)); ++ ++ return u; ++} ++ ++static void sleep(int delay) ++{ ++ int tick, last_tick = currticks(); ++ ++ delay *= 18; ++ ++ while(delay--) { ++ while((tick = currticks()) == last_tick) { } ++ last_tick = tick; ++ } ++} ++ ++static void wait_for_key() ++{ ++ printf("Press a key to continue..."); ++ getkey(); ++ printf("\r \r"); ++} ++ ++ ++/* ++ * Leave that much space on the heap. Everything else goes to the graphics ++ * functions. ++ * ++ * 0x2000 is _not_ enough ++ */ ++#define MIN_HEAP_SIZE 0x4000 ++#define MIN_GFX_FREE 0x1000 ++ ++#define SC_BOOTLOADER 0 ++#define SC_FAILSAFE 3 ++#define SC_SYSCONFIG_SIZE 4 ++#define SC_BOOTLOADER_SEG 8 ++#define SC_XMEM_0 24 ++#define SC_XMEM_1 26 ++#define SC_XMEM_2 28 ++#define SC_XMEM_3 30 ++#define SC_FILE 32 ++#define SC_ARCHIVE_START 36 ++#define SC_ARCHIVE_END 40 ++#define SC_MEM0_START 44 ++#define SC_MEM0_END 48 ++ ++/* ++ * Does normally not return. ++ */ ++static void ++run_graphics_menu (char *menu_entries, char *config_entries, int num_entries, ++ char *heap, int entryno) ++{ ++ unsigned char *buf, *buf_ext; ++ unsigned buf_size, buf_ext_size, code_start, file_start; ++ char *s, *t, *t2, *cfg, *new_config, *p; ++ char *saved_heap; ++ int i, j, max_len, gfx_file_size, verbose; ++ int selected_entry; ++ gfx_data_t *gfx_data; ++ char *cmd_buf; ++ unsigned mem0_start, mem0_end, file_len; ++ ++ /* ++ * check gfx_data_t struct offsets for consistency; gcc will optimize away ++ * the whole block ++ */ ++ ++ /* dummy function to make ld fail */ ++ { ++ extern void wrong_struct_size(void); ++ #define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size(); ++ gfx_ofs_check(ok); ++ gfx_ofs_check(code_seg); ++ gfx_ofs_check(jmp_table); ++ gfx_ofs_check(sys_cfg); ++ gfx_ofs_check(cmdline); ++ gfx_ofs_check(cmdline_len); ++ gfx_ofs_check(menu_list); ++ gfx_ofs_check(menu_default_entry); ++ gfx_ofs_check(menu_entries); ++ gfx_ofs_check(menu_entry_len); ++ gfx_ofs_check(args_list); ++ gfx_ofs_check(args_entry_len); ++ gfx_ofs_check(timeout); ++ #undef gfx_ofs_check ++ } ++ ++ if(!num_entries) return; ++ ++ graphics_data = gfx_data = (gfx_data_t *) heap; ++ heap += sizeof *gfx_data; ++ memset(gfx_data, 0, sizeof *gfx_data); ++ ++ gfx_data->sys_cfg[SC_BOOTLOADER] = 2; /* bootloader: grub */ ++ gfx_data->sys_cfg[SC_SYSCONFIG_SIZE] = 52; /* config data size */ ++ *(unsigned short *) (gfx_data->sys_cfg + SC_BOOTLOADER_SEG) = (unsigned) gfx_data >> 4; /* segment */ ++ gfx_data->sys_cfg[SC_XMEM_0] = 0x28; /* 8MB @ 2MB, see buf_ext below */ ++ // gfx_data->sys_cfg[SC_XMEM_1] = 0xYZ; /* Z MB @ Y MB */ ++ verbose = (*(unsigned char *) 0x417) & 3 ? 1 : 0; /* SHIFT pressed */ ++ gfx_data->sys_cfg[SC_FAILSAFE] = verbose; ++ ++ gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0; ++ ++ ++ /* setup command line edit buffer */ ++ ++ gfx_data->cmdline_len = 256; ++ ++ gfx_data->cmdline = heap; ++ heap += gfx_data->cmdline_len; ++ memset(gfx_data->cmdline, 0, gfx_data->cmdline_len); ++ ++ cmd_buf = heap; ++ heap += GFX_CMD_BUF_SIZE; ++ ++ /* setup menu entries */ ++ ++ for(i = max_len = 0; i < num_entries; i++) { ++ j = strlen(get_entry(menu_entries, i, 0)); ++ if(j > max_len) max_len = j; ++ } ++ ++ if(!max_len) return; ++ ++ gfx_data->menu_entry_len = max_len + 1; ++ gfx_data->menu_entries = num_entries; ++ ++ gfx_data->menu_list = heap; ++ heap += gfx_data->menu_entry_len * gfx_data->menu_entries; ++ ++ memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries); ++ ++ for(i = 0; i < (int) gfx_data->menu_entries; i++) { ++ strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0)); ++ } ++ ++ gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len; ++ ++ ++ /* setup list of kernel args */ ++ ++ for(i = max_len = 0; i < num_entries; i++) { ++ s = get_kernel_args(get_entry(config_entries, i, 1), cmd_buf); ++ j = strlen(s); ++ if(j > max_len) max_len = j; ++ } ++ ++ gfx_data->args_entry_len = max_len + 1; ++ ++ gfx_data->args_list = heap; ++ heap += gfx_data->args_entry_len * gfx_data->menu_entries; ++ ++ memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries); ++ ++ for(i = 0; i < (int) gfx_data->menu_entries; i++) { ++ strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1), cmd_buf)); ++ } ++ ++ ++ /* go back here when we no longer need the graphics data */ ++ saved_heap = heap; ++ ++ ++ /* get memory area to be used by graphics functions */ ++ ++ /* use 8MB starting at 2MB as file buffer; see SC_XMEM_0 above (A20 is enabled anyway) */ ++ buf_ext = (unsigned char *) (2 << 20); ++ buf_ext_size = 8 << 20; ++ ++ /* must be 16-byte aligned */ ++ buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf); ++ ++ buf_size = stack_ptr() - buf - MIN_HEAP_SIZE; ++ buf_size &= ~0xf; ++ ++ mem0_start = (unsigned) buf; ++ mem0_end = mem0_start + buf_size; ++ ++ if(verbose) { ++ printf("low memory 0x%x - 0x%x (%d bytes)\n", mem0_start, mem0_end, buf_size); ++ wait_for_key(); ++ } ++ ++ heap += buf_size; ++ ++ /* read the file */ ++ ++ if(!grub_open(graphics_file)) { ++ printf("%s: file not found\n", graphics_file); ++ sleep(5); ++ heap = saved_heap; ++ return; ++ } ++ ++ gfx_file_size = grub_read(buf_ext, buf_ext_size); ++ ++ grub_close(); ++ ++ if(gfx_file_size <= 0) { ++ printf("%s: read error\n", graphics_file); ++ sleep(5); ++ heap = saved_heap; ++ return; ++ } ++ ++ if(verbose) { ++ printf("%s: %d bytes (%d bytes left)\n", graphics_file, gfx_file_size, buf_ext_size - gfx_file_size); ++ wait_for_key(); ++ } ++ ++ /* locate file inside cpio archive */ ++ if(!(code_start = find_file(buf_ext, gfx_file_size, &file_start, &file_len))) { ++ printf("%s: invalid file format\n", graphics_file); ++ sleep(5); ++ heap = saved_heap; ++ return; ++ } ++ ++ if(verbose) { ++ printf("init: start 0x%x, len %d; code offset 0x%x\n", file_start, file_len, code_start); ++ wait_for_key(); ++ } ++ ++ if(file_len - code_start + MIN_GFX_FREE > buf_size) { ++ printf("not enough free memory: %d extra bytes need\n", file_len - code_start + MIN_GFX_FREE - buf_size); ++ sleep(5); ++ heap = saved_heap; ++ return; ++ } ++ ++ memcpy((void *) buf, (void *) (buf_ext + file_start + code_start), file_len - code_start); ++ ++ mem0_start += file_len - code_start; ++ mem0_start = (mem0_start + 3) & ~3; /* align */ ++ ++ /* init interface to graphics functions */ ++ ++ *(unsigned *) (gfx_data->sys_cfg + SC_FILE) = (unsigned) buf_ext + file_start; ++ *(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_START) = (unsigned) buf_ext; ++ *(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_END) = (unsigned) buf_ext + gfx_file_size; ++ *(unsigned *) (gfx_data->sys_cfg + SC_MEM0_START) = mem0_start; ++ *(unsigned *) (gfx_data->sys_cfg + SC_MEM0_END) = mem0_end; ++ ++ gfx_data->code_seg = (unsigned) buf >> 4; ++ ++ if(verbose) { ++ printf("init 0x%x, archive 0x%x - 0x%x, low mem 0x%x - 0x%x\ncode seg 0x%x\n", ++ (unsigned) buf_ext + file_start, ++ (unsigned) buf_ext, (unsigned) buf_ext + gfx_file_size, ++ mem0_start, mem0_end, gfx_data->code_seg ++ ); ++ wait_for_key(); ++ } ++ ++ for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) { ++ gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) buf)[i]; ++ } ++ ++ if(verbose) { ++ for(i = 0; i < 12; i++) { ++ printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]); ++ } ++ ++ for(i = 0; i < gfx_data->menu_entries; i++) { ++ printf("\"%s\" -- \"%s\"\n", ++ gfx_data->menu_list + i * gfx_data->menu_entry_len, ++ gfx_data->args_list + i * gfx_data->args_entry_len ++ ); ++ } ++ ++ printf("default: \"%s\"\n", gfx_data->menu_default_entry); ++ wait_for_key(); ++ } ++ ++ /* switch to graphics mode */ ++ ++ if(gfx_init(gfx_data)) { ++ printf("graphics initialization failed\n"); ++ sleep(5); ++ heap = saved_heap; ++ return; ++ } ++ ++ gfx_setup_menu(gfx_data); ++ ++ i = gfx_input(gfx_data, &selected_entry); ++ ++ /* ESC -> show text menu */ ++ if(i == 1) { ++ gfx_done(gfx_data); ++ grub_timeout = -1; ++ ++ heap = saved_heap; ++ return; ++ } ++ ++ gfx_done(gfx_data); ++ ++ heap = saved_heap; /* free most of the graphics data */ ++ ++ // printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry); ++ ++ if(selected_entry < 0 || selected_entry > num_entries) return; ++ ++ /* for 'savedefault' */ ++ current_entryno = selected_entry; ++ ++ ++ /* create new config with modified kernel option */ ++ ++ cfg = get_entry(config_entries, selected_entry, 1); ++ ++ new_config = heap; ++ ++ for(p = gfx_data->cmdline, i = 0; ; i++) { ++ s = get_entry(cfg, i, 0); ++ if(!*s) { ++ if(!i) *heap++ = 0; ++ *heap++ = 0; ++ break; ++ } ++ /* note: must match get_kernel_args() */ ++ if( ++ (!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) && ++ (s[6] == ' ' || s[6] == '\t') ++ ) { ++ t = skip_to(0, s); ++ t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL; ++ if(*t) t = skip_to(0, t); ++ if(t2 && t2 < t) { /* module is likely a normal initrd -> skip */ ++ strcpy(heap, s); ++ heap += strlen(s) + 1; ++ continue; ++ } ++ memmove(heap, s, t - s); ++ heap += t - s; ++ *heap++ = ' '; ++ while(*p && *p != GFX_CMD_SEP) *heap++ = *p++; ++ *heap++ = 0; ++ if(*p == GFX_CMD_SEP) p++; ++ } ++ else { ++ strcpy(heap, s); ++ heap += strlen(s) + 1; ++ } ++ } ++ ++ *heap++ = 0; ++ ++ // hexdump(new_config, heap - new_config); ++ // getkey(); ++ ++ run_script(new_config, heap); ++} ++ ++ + static int + get_line_from_config (char *cmdline, int maxlen, int read_from_file) + { +@@ -1059,9 +1557,12 @@ cmain (void) + } + else + { +- /* Run menu interface. */ +- run_menu (menu_entries, config_entries, num_entries, +- menu_entries + menu_len, default_entry); ++ if (*graphics_file && !password && show_menu && grub_timeout) ++ { ++ run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry); ++ } ++ /* Run menu interface. */ ++ run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry); + } + } + } diff --git a/sys-boot/grub/files/grub-0.97-uuid.patch b/sys-boot/grub/files/grub-0.97-uuid.patch new file mode 100644 index 00000000..f99670a8 --- /dev/null +++ b/sys-boot/grub/files/grub-0.97-uuid.patch @@ -0,0 +1,5406 @@ +=== modified file 'Makefile.am' +--- grub-0.97.orig/Makefile.am 2004-04-23 13:39:01 +0000 ++++ grub-0.97/Makefile.am 2008-07-09 17:23:44 +0000 +@@ -1,4 +1,9 @@ + # Do not change this order if you don't know what you are doing. + AUTOMAKE_OPTIONS = 1.7 gnu +-SUBDIRS = netboot stage2 stage1 lib grub util docs ++if UUID_SUPPORT ++SUBDIRS = libvolume_id netboot stage2 stage1 lib grub util docs ++else ++SUBDIRS = netboot stage2 stage1 lib grub util docs ++endif ++ + EXTRA_DIST = BUGS MAINTENANCE + +=== modified file 'configure.ac' +--- grub-0.97.orig/configure.ac 2008-01-28 18:41:45 +0000 ++++ grub-0.97/configure.ac 2008-07-09 17:23:44 +0000 +@@ -605,6 +606,11 @@ + [ --disable-serial disable serial terminal support]) + AM_CONDITIONAL(SERIAL_SUPPORT, test "x$enable_serial" != xno) + ++dnl UUID scanning ++AC_ARG_ENABLE(uuid, ++ [ --disable-uuid disable uuid scanning support]) ++AM_CONDITIONAL(UUID_SUPPORT, test "x$enable_uuid" != xno) ++ + dnl Simulation of the slowness of a serial device. + AC_ARG_ENABLE(serial-speed-simulation, + [ --enable-serial-speed-simulation +@@ -666,5 +672,6 @@ + docs/Makefile lib/Makefile util/Makefile \ + grub/Makefile netboot/Makefile util/grub-image \ + util/grub-install util/grub-md5-crypt \ +- util/grub-terminfo util/grub-set-default]) ++ util/grub-terminfo util/grub-set-default \ ++ libvolume_id/Makefile]) + AC_OUTPUT + +=== modified file 'grub/Makefile.am' +--- grub-0.97.orig/grub/Makefile.am 2005-02-02 20:40:05 +0000 ++++ grub-0.97/grub/Makefile.am 2008-07-09 17:23:44 +0000 +@@ -16,4 +16,9 @@ + AM_CFLAGS = $(GRUB_CFLAGS) + + grub_SOURCES = main.c asmstub.c +-grub_LDADD = ../stage2/libgrub.a ../lib/libcommon.a $(GRUB_LIBS) ++ ++if UUID_SUPPORT ++grub_LDADD = ../stage2/libgrub.a ../lib/libcommon.a ../libvolume_id/libvolume_id.a $(GRUB_LIBS) ++else ++grub_LDADD = ../stage2/libgrub.a ../lib/libcommon.a $(GRUB_LIBS) ++endif + +=== added directory 'libvolume_id' +=== added file 'libvolume_id/Makefile.am' +--- grub-0.97.orig/libvolume_id/Makefile.am 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/Makefile.am 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,27 @@ ++noinst_LIBRARIES = libvolume_id.a ++ ++AM_CFLAGS = $(STAGE2_CFLAGS) -I$(top_srcdir)/stage2 -I$(top_srcdir)/stage1 ++ ++LIBVOLUME_ID_FS_SUPPORTED = ext.c fat.c hfs.c jfs.c \ ++ luks.c ntfs.c ocfs.c reiserfs.c \ ++ xfs.c ++ ++LIBVOLUME_ID_FS_UNSUPPORTED = cramfs.c gfs.c hpfs.c iso9660.c \ ++ lvm.c minix.c romfs.c squashfs.c \ ++ sysv.c udf.c ufs.c vxfs.c ++ ++LIBVOLUME_ID_RAID_SUPPORTED = ddf_raid.c ++ ++LIBVOLUME_ID_RAID_UNSUPPORTED = adaptec_raid.c highpoint.c isw_raid.c \ ++ jmicron_raid.c linux_raid.c lsi_raid.c \ ++ nvidia_raid.c promise_raid.c silicon_raid.c \ ++ via_raid.c ++ ++LIBVOLUME_ID_MISC_UNSUPPORTED = linux_swap.c netware.c ++ ++libvolume_id_a_SOURCES = $(LIBVOLUME_ID_FS_SUPPORTED) \ ++ $(LIBVOLUME_ID_RAID_SUPPORTED) \ ++ $(LIBVOLUME_ID_FS_UNSUPPORTED) \ ++ $(LIBVOLUME_ID_RAID_UNSUPPORTED) \ ++ volume_id.h volume_id.c util.c util.h misc.c ++ + +=== added file 'libvolume_id/adaptec_raid.c' +--- grub-0.97.orig/libvolume_id/adaptec_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/adaptec_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,107 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct adaptec_meta { ++ uint32_t b0idcode; ++ uint8_t lunsave[8]; ++ uint16_t sdtype; ++ uint16_t ssavecyl; ++ uint8_t ssavehed; ++ uint8_t ssavesec; ++ uint8_t sb0flags; ++ uint8_t jbodEnable; ++ uint8_t lundsave; ++ uint8_t svpdirty; ++ uint16_t biosInfo; ++ uint16_t svwbskip; ++ uint16_t svwbcln; ++ uint16_t svwbmax; ++ uint16_t res3; ++ uint16_t svwbmin; ++ uint16_t res4; ++ uint16_t svrcacth; ++ uint16_t svwcacth; ++ uint16_t svwbdly; ++ uint8_t svsdtime; ++ uint8_t res5; ++ uint16_t firmval; ++ uint16_t firmbln; ++ uint32_t firmblk; ++ uint32_t fstrsvrb; ++ uint16_t svBlockStorageTid; ++ uint16_t svtid; ++ uint8_t svseccfl; ++ uint8_t res6; ++ uint8_t svhbanum; ++ uint8_t resver; ++ uint32_t drivemagic; ++ uint8_t reserved[20]; ++ uint8_t testnum; ++ uint8_t testflags; ++ uint16_t maxErrorCount; ++ uint32_t count; ++ uint32_t startTime; ++ uint32_t interval; ++ uint8_t tstxt0; ++ uint8_t tstxt1; ++ uint8_t serNum[32]; ++ uint8_t res8[102]; ++ uint32_t fwTestMagic; ++ uint32_t fwTestSeqNum; ++ uint8_t fwTestRes[8]; ++ uint8_t smagic[4]; ++ uint32_t raidtbl; ++ uint16_t raidline; ++ uint8_t res9[0xF6]; ++} PACKED; ++ ++int volume_id_probe_adaptec_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct adaptec_meta *ad; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ ad = (struct adaptec_meta *) buf; ++ if (memcmp((char*)ad->smagic, "DPTM", 4) != 0) ++ return -1; ++ ++ if (ad->b0idcode != be32_to_cpu(0x37FC4D1E)) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u", ad->resver); ++ id->type = "adaptec_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/cramfs.c' +--- grub-0.97.orig/libvolume_id/cramfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/cramfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,60 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct cramfs_super { ++ uint8_t magic[4]; ++ uint32_t size; ++ uint32_t flags; ++ uint32_t future; ++ uint8_t signature[16]; ++ struct cramfs_info { ++ uint32_t crc; ++ uint32_t edition; ++ uint32_t blocks; ++ uint32_t files; ++ } PACKED info; ++ uint8_t name[16]; ++} PACKED; ++ ++int volume_id_probe_cramfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct cramfs_super *cs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ cs = (struct cramfs_super *) volume_id_get_buffer(id, off, 0x200); ++ if (cs == NULL) ++ return -1; ++ ++ if (memcmp((char*)cs->magic, "\x45\x3d\xcd\x28", 4) == 0 || memcmp((char*)cs->magic, "\x28\xcd\x3d\x45", 4) == 0) { ++ volume_id_set_label_raw(id, cs->name, 16); ++ volume_id_set_label_string(id, cs->name, 16); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "cramfs"; ++ return 0; ++ } ++ ++ return -1; ++} + +=== added file 'libvolume_id/ddf_raid.c' +--- grub-0.97.orig/libvolume_id/ddf_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ddf_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,60 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++/* http://www.snia.org/standards/home */ ++ ++#define DDF_HEADER 0xDE11DE11 ++#define DDF_GUID_LENGTH 24 ++#define DDF_REV_LENGTH 8 ++ ++static struct ddf_header { ++ uint32_t signature; ++ uint32_t crc; ++ uint8_t guid[DDF_GUID_LENGTH]; ++ uint8_t ddf_rev[DDF_REV_LENGTH]; ++} PACKED *ddf; ++ ++int volume_id_probe_ddf_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint64_t ddf_off = ((size / 0x200)-1) * 0x200; ++ const uint8_t *buf; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ if (size < 0x10000) ++ return -1; ++ ++ buf = volume_id_get_buffer(id, off + ddf_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ddf = (struct ddf_header *) buf; ++ ++ if (ddf->signature != cpu_to_be32(DDF_HEADER)) ++ return -1; ++ ++ volume_id_set_uuid(id, ddf->guid, DDF_GUID_LENGTH, UUID_STRING); ++ strcpy(id->type_version, (char*) ddf->ddf_rev); ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "ddf_raid_member"; ++ return 0; ++} + +=== added file 'libvolume_id/ext.c' +--- grub-0.97.orig/libvolume_id/ext.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ext.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,129 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct ext2_super_block { ++ uint32_t s_inodes_count; ++ uint32_t s_blocks_count; ++ uint32_t s_r_blocks_count; ++ uint32_t s_free_blocks_count; ++ uint32_t s_free_inodes_count; ++ uint32_t s_first_data_block; ++ uint32_t s_log_block_size; ++ uint32_t s_log_frag_size; ++ uint32_t s_blocks_per_group; ++ uint32_t s_frags_per_group; ++ uint32_t s_inodes_per_group; ++ uint32_t s_mtime; ++ uint32_t s_wtime; ++ uint16_t s_mnt_count; ++ uint16_t s_max_mnt_count; ++ uint16_t s_magic; ++ uint16_t s_state; ++ uint16_t s_errors; ++ uint16_t s_minor_rev_level; ++ uint32_t s_lastcheck; ++ uint32_t s_checkinterval; ++ uint32_t s_creator_os; ++ uint32_t s_rev_level; ++ uint16_t s_def_resuid; ++ uint16_t s_def_resgid; ++ uint32_t s_first_ino; ++ uint16_t s_inode_size; ++ uint16_t s_block_group_nr; ++ uint32_t s_feature_compat; ++ uint32_t s_feature_incompat; ++ uint32_t s_feature_ro_compat; ++ uint8_t s_uuid[16]; ++ uint8_t s_volume_name[16]; ++} PACKED; ++ ++#define EXT_SUPER_MAGIC 0xEF53 ++#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 ++#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 ++#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 ++#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 ++#define EXT4_FEATURE_INCOMPAT_MMP 0x0100 ++ ++#define EXT_SUPERBLOCK_OFFSET 0x400 ++ ++#define EXT3_MIN_BLOCK_SIZE 0x400 ++#define EXT3_MAX_BLOCK_SIZE 0x1000 ++ ++int volume_id_probe_ext(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct ext2_super_block *es; ++ size_t bsize; ++ uint32_t feature_compat; ++ uint32_t feature_incompat; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ es = (struct ext2_super_block *) volume_id_get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200); ++ if (es == NULL) ++ return -1; ++ ++ if (es->s_magic != cpu_to_le16(EXT_SUPER_MAGIC)) ++ return -1; ++ ++ bsize = 0x400 << le32_to_cpu(es->s_log_block_size); ++ dbg("ext blocksize 0x%zx", bsize); ++ if (bsize < EXT3_MIN_BLOCK_SIZE || bsize > EXT3_MAX_BLOCK_SIZE) { ++ dbg("invalid ext blocksize"); ++ return -1; ++ } ++ ++ volume_id_set_label_raw(id, es->s_volume_name, 16); ++ volume_id_set_label_string(id, es->s_volume_name, 16); ++ volume_id_set_uuid(id, es->s_uuid, 0, UUID_DCE); ++ sprintf(id->type_version, "%u.%u", ++ le32_to_cpu(es->s_rev_level), le16_to_cpu(es->s_minor_rev_level)); ++ ++ feature_compat = le32_to_cpu(es->s_feature_compat); ++ feature_incompat = le32_to_cpu(es->s_feature_incompat); ++ ++ /* check for external journal device */ ++ if ((feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) != 0) { ++ volume_id_set_usage(id, VOLUME_ID_OTHER); ++ id->type = "jbd"; ++ goto out; ++ } ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ ++ if ((feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) != 0 || ++ (feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) != 0 || ++ (feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) != 0) { ++ id->type = "ext4"; ++ goto out; ++ } ++ ++ if ((feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) { ++ id->type = "ext3"; ++ goto out; ++ } ++ ++ id->type = "ext2"; ++ ++out: ++ return 0; ++} + +=== added file 'libvolume_id/fat.c' +--- grub-0.97.orig/libvolume_id/fat.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/fat.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,482 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Copyright (C) 2007 Ryan Lortie <desrt@desrt.ca> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define FAT12_MAX 0xff5 ++#define FAT16_MAX 0xfff5 ++#define FAT_ATTR_VOLUME_ID 0x08 ++#define FAT_ATTR_DIR 0x10 ++#define FAT_ATTR_LONG_NAME 0x0f ++#define FAT_ATTR_MASK 0x3f ++#define FAT_ENTRY_FREE 0xe5 ++ ++#define VFAT_LFN_SEQ_MASK 0x3f ++#define VFAT_LFN_SEQ_LAST 0x40 ++#define VFAT_LFN_SEQ_MAX 20 ++#define VFAT_LFN_CHARS_PER_ENTRY (5 + 6 + 2) ++#define VFAT_LOWERCASE_NAME 0x10 ++#define VFAT_LOWERCASE_EXT 0x08 ++ ++struct vfat_super_block { ++ uint8_t boot_jump[3]; ++ uint8_t sysid[8]; ++ uint16_t sector_size; ++ uint8_t sectors_per_cluster; ++ uint16_t reserved; ++ uint8_t fats; ++ uint16_t dir_entries; ++ uint16_t sectors; ++ uint8_t media; ++ uint16_t fat_length; ++ uint16_t secs_track; ++ uint16_t heads; ++ uint32_t hidden; ++ uint32_t total_sect; ++ union { ++ struct fat_super_block { ++ uint8_t unknown[3]; ++ uint8_t serno[4]; ++ uint8_t label[11]; ++ uint8_t magic[8]; ++ uint8_t dummy2[192]; ++ uint8_t pmagic[2]; ++ } PACKED fat; ++ struct fat32_super_block { ++ uint32_t fat32_length; ++ uint16_t flags; ++ uint8_t version[2]; ++ uint32_t root_cluster; ++ uint16_t fsinfo_sector; ++ uint16_t backup_boot; ++ uint16_t reserved2[6]; ++ uint8_t unknown[3]; ++ uint8_t serno[4]; ++ uint8_t label[11]; ++ uint8_t magic[8]; ++ uint8_t dummy2[164]; ++ uint8_t pmagic[2]; ++ } PACKED fat32; ++ } PACKED type; ++} PACKED; ++ ++struct fat32_fsinfo { ++ uint8_t signature1[4]; ++ uint32_t reserved1[120]; ++ uint8_t signature2[4]; ++ uint32_t free_clusters; ++ uint32_t next_cluster; ++ uint32_t reserved2[4]; ++} PACKED; ++ ++struct vfat_dir_entry { ++ uint8_t name[11]; ++ uint8_t attr; ++ uint8_t lowercase; ++ uint8_t fine_time_creat; ++ uint16_t time_creat; ++ uint16_t date_creat; ++ uint16_t date_acc; ++ uint16_t cluster_high; ++ uint16_t time_write; ++ uint16_t date_write; ++ uint16_t cluster_low; ++ uint32_t size; ++} PACKED; ++ ++ ++struct vfat_lfn_entry { ++ uint8_t seq; ++ uint16_t name0[5]; ++ uint8_t attr; ++ uint8_t reserved; ++ uint8_t cksum; ++ uint16_t name1[6]; ++ uint16_t cluster; ++ uint16_t name2[2]; ++} PACKED; ++ ++static uint8_t fat_lfn_checksum(const uint8_t name[11]) ++{ ++ uint8_t cksum = 0; ++ int i; ++ ++ /* http://en.wikipedia.org/wiki/File_Allocation_Table */ ++ for (i = 0; i < 11; i++) ++ cksum = ((cksum & 1) ? 0x80 : 0) + (cksum >> 1) + name[i]; ++ ++ return cksum; ++} ++ ++static size_t fat_read_lfn(uint8_t *filename, size_t fnsize, ++ struct vfat_dir_entry *direntry, ++ struct vfat_dir_entry *entry) ++{ ++ uint8_t buffer[VFAT_LFN_SEQ_MAX * VFAT_LFN_CHARS_PER_ENTRY * 2]; ++ uint8_t expected_seq = 1; ++ uint8_t cksum; ++ size_t len = 0; ++ size_t fnlen = 0; ++ ++ cksum = fat_lfn_checksum(entry->name); ++ ++ while (--entry >= direntry) { ++ struct vfat_lfn_entry *lfn = (struct vfat_lfn_entry *) entry; ++ ++ if (expected_seq > VFAT_LFN_SEQ_MAX) ++ break; ++ ++ if ((lfn->attr & FAT_ATTR_MASK) != FAT_ATTR_LONG_NAME) ++ break; ++ ++ if (lfn->cksum != cksum) ++ break; ++ ++ if ((lfn->seq & VFAT_LFN_SEQ_MASK) != expected_seq++) ++ break; ++ ++ if (lfn->cluster != 0) ++ break; ++ ++ /* extra paranoia -- should never happen */ ++ if (len + sizeof(lfn->name0) + sizeof(lfn->name1) + ++ sizeof(lfn->name2) > sizeof(buffer)) ++ break; ++ ++ memcpy (&buffer[len], lfn->name0, sizeof(lfn->name0)); ++ len += sizeof(lfn->name0); ++ memcpy (&buffer[len], lfn->name1, sizeof(lfn->name1)); ++ len += sizeof(lfn->name1); ++ memcpy (&buffer[len], lfn->name2, sizeof(lfn->name2)); ++ len += sizeof(lfn->name2); ++ ++ if (lfn->seq & VFAT_LFN_SEQ_LAST) { ++ fnlen = volume_id_set_unicode16(filename, fnsize, buffer, LE, len); ++ break; ++ } ++ } ++ ++ return fnlen; ++} ++ ++static size_t fat_read_filename(uint8_t *filename, size_t fnsize, ++ struct vfat_dir_entry *direntry, struct vfat_dir_entry *entry) ++{ ++ size_t len; ++ int i; ++ ++ /* check if maybe we have LFN entries */ ++ len = fat_read_lfn(filename, fnsize, direntry, entry); ++ if (len > 0) ++ goto out; ++ ++ /* else, read the normal 8.3 name */ ++ for (i = 0; i < 11; i++) { ++ if (entry->lowercase & ((i < 8) ? VFAT_LOWERCASE_NAME : VFAT_LOWERCASE_EXT)) ++ filename[i] = tolower(entry->name[i]); ++ else ++ filename[i] = entry->name[i]; ++ } ++ len = 11; ++ ++out: ++ filename[len] = '\0'; ++ return len; ++} ++ ++/* fills filename, returns string length */ ++static size_t get_fat_attr_volume_id(uint8_t *filename, size_t fnsize, ++ struct vfat_dir_entry *direntry, unsigned int count) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < count; i++) { ++ /* end marker */ ++ if (direntry[i].name[0] == 0x00) { ++ dbg("end of dir"); ++ break; ++ } ++ ++ /* empty entry */ ++ if (direntry[i].name[0] == FAT_ENTRY_FREE) ++ continue; ++ ++ /* long name */ ++ if ((direntry[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME) ++ continue; ++ ++ if ((direntry[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) { ++ /* labels do not have file data */ ++ if (direntry[i].cluster_high != 0 || direntry[i].cluster_low != 0) ++ continue; ++ ++ dbg("found ATTR_VOLUME_ID id in root dir"); ++ return fat_read_filename(filename, fnsize, direntry, &direntry[i]); ++ } ++ ++ dbg("skip dir entry"); ++ } ++ ++ return 0; ++} ++ ++int volume_id_probe_vfat(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint8_t filename[255 * 3]; ++ struct vfat_super_block *vs; ++ struct vfat_dir_entry *direntry; ++ struct fat32_fsinfo *fsinfo; ++ uint16_t sector_size; ++ uint16_t dir_entries; ++ uint32_t sect_count; ++ uint16_t reserved; ++ uint32_t fat_size; ++ uint32_t root_cluster; ++ uint32_t dir_size; ++ uint32_t cluster_count; ++ uint16_t fat_length; ++ uint32_t fat32_length; ++ uint64_t root_start; ++ uint32_t start_data_sect; ++ uint16_t root_dir_entries; ++ uint16_t fsinfo_sect; ++ uint8_t *buf; ++ uint32_t buf_size; ++ uint32_t next; ++ int maxloop; ++ size_t fnlen; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off, 0x400); ++ if (buf == NULL) ++ return -1; ++ ++ /* check signature */ ++ if (buf[510] != 0x55 || buf[511] != 0xaa) ++ return -1; ++ ++ vs = (struct vfat_super_block *) buf; ++ if (memcmp((char*)vs->sysid, "NTFS", 4) == 0) ++ return -1; ++ ++ /* believe only that's fat, don't trust the version */ ++ if (memcmp((char*)vs->type.fat32.magic, "MSWIN", 5) == 0) ++ goto magic; ++ ++ if (memcmp((char*)vs->type.fat32.magic, "FAT32 ", 8) == 0) ++ goto magic; ++ ++ if (memcmp((char*)vs->type.fat.magic, "FAT16 ", 8) == 0) ++ goto magic; ++ ++ if (memcmp((char*)vs->type.fat.magic, "MSDOS", 5) == 0) ++ goto magic; ++ ++ if (memcmp((char*)vs->type.fat.magic, "FAT12 ", 8) == 0) ++ goto magic; ++ ++ /* some old floppies don't have a magic, expect the boot jump address to match */ ++ if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) && ++ vs->boot_jump[0] != 0xe9) ++ return -1; ++ ++magic: ++ /* reserverd sector count */ ++ if (!vs->reserved) ++ return -1; ++ ++ /* fat count */ ++ if (!vs->fats) ++ return -1; ++ ++ /* media check */ ++ if (vs->media < 0xf8 && vs->media != 0xf0) ++ return -1; ++ ++ /* cluster size check */ ++ if (vs->sectors_per_cluster == 0 || ++ (vs->sectors_per_cluster & (vs->sectors_per_cluster-1))) ++ return -1; ++ ++ /* sector size check */ ++ sector_size = le16_to_cpu(vs->sector_size); ++ if (sector_size == 0 || ((sector_size & (sector_size-1)) != 0)) ++ return -1; ++ ++ dbg("sector_size 0x%x", sector_size); ++ dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster); ++ ++ dir_entries = le16_to_cpu(vs->dir_entries); ++ reserved = le16_to_cpu(vs->reserved); ++ dbg("reserved 0x%x", reserved); ++ ++ sect_count = le16_to_cpu(vs->sectors); ++ if (sect_count == 0) ++ sect_count = le32_to_cpu(vs->total_sect); ++ dbg("sect_count 0x%x", sect_count); ++ ++ fat_length = le16_to_cpu(vs->fat_length); ++ dbg("fat_length 0x%x", fat_length); ++ fat32_length = le32_to_cpu(vs->type.fat32.fat32_length); ++ dbg("fat32_length 0x%x", fat32_length); ++ ++ if (fat_length) ++ fat_size = fat_length * vs->fats; ++ else if (fat32_length) ++ fat_size = fat32_length * vs->fats; ++ else ++ return -1; ++ dbg("fat_size 0x%x", fat_size); ++ ++ dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) + ++ (sector_size-1)) / sector_size; ++ dbg("dir_size 0x%x", dir_size); ++ ++ cluster_count = sect_count - (reserved + fat_size + dir_size); ++ cluster_count /= vs->sectors_per_cluster; ++ dbg("cluster_count 0x%x", cluster_count); ++ ++ /* must be FAT32 */ ++ if (!fat_length && fat32_length) ++ goto fat32; ++ ++ /* cluster_count tells us the format */ ++ if (cluster_count < FAT12_MAX) ++ strcpy(id->type_version, "FAT12"); ++ else if (cluster_count < FAT16_MAX) ++ strcpy(id->type_version, "FAT16"); ++ else ++ goto fat32; ++ ++ /* the label may be an attribute in the root directory */ ++ root_start = (reserved + fat_size) * sector_size; ++ dbg("root dir start 0x%llx", (unsigned long long) root_start); ++ root_dir_entries = le16_to_cpu(vs->dir_entries); ++ dbg("expected entries 0x%x", root_dir_entries); ++ ++ buf_size = root_dir_entries * sizeof(struct vfat_dir_entry); ++ buf = volume_id_get_buffer(id, off + root_start, buf_size); ++ if (buf == NULL) ++ goto found; ++ ++ direntry = (struct vfat_dir_entry*) buf; ++ ++ fnlen = get_fat_attr_volume_id(filename, sizeof(filename), direntry, root_dir_entries); ++ ++ vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (vs == NULL) ++ return -1; ++ ++ if (fnlen > 0 && memcmp((char*)filename, "NO NAME ", 11) != 0) { ++ volume_id_set_label_raw(id, filename, fnlen); ++ volume_id_set_label_string(id, filename, fnlen); ++ } else if (memcmp((char*)vs->type.fat.label, "NO NAME ", 11) != 0) { ++ volume_id_set_label_raw(id, vs->type.fat.label, 11); ++ volume_id_set_label_string(id, vs->type.fat.label, 11); ++ } ++ volume_id_set_uuid(id, vs->type.fat.serno, 0, UUID_DOS); ++ goto found; ++ ++fat32: ++ /* FAT32 should have a valid signature in the fsinfo block */ ++ fsinfo_sect = le16_to_cpu(vs->type.fat32.fsinfo_sector); ++ buf = volume_id_get_buffer(id, off + (fsinfo_sect * sector_size), 0x200); ++ if (buf == NULL) ++ return -1; ++ fsinfo = (struct fat32_fsinfo *) buf; ++ if (memcmp((char*)fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0) ++ return -1; ++ if (memcmp((char*)fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0) ++ return -1 ; ++ ++ vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (vs == NULL) ++ return -1; ++ ++ strcpy(id->type_version, "FAT32"); ++ ++ /* FAT32 root dir is a cluster chain like any other directory */ ++ buf_size = vs->sectors_per_cluster * sector_size; ++ root_cluster = le32_to_cpu(vs->type.fat32.root_cluster); ++ dbg("root dir cluster %u", root_cluster); ++ start_data_sect = reserved + fat_size; ++ ++ next = root_cluster; ++ maxloop = 100; ++ while (--maxloop) { ++ uint32_t next_sect_off; ++ uint64_t next_off; ++ uint64_t fat_entry_off; ++ int count; ++ ++ dbg("next cluster %u", next); ++ next_sect_off = (next - 2) * vs->sectors_per_cluster; ++ next_off = (start_data_sect + next_sect_off) * sector_size; ++ dbg("cluster offset 0x%llx", (unsigned long long) next_off); ++ ++ /* get cluster */ ++ buf = volume_id_get_buffer(id, off + next_off, buf_size); ++ if (buf == NULL) ++ goto found; ++ ++ direntry = (struct vfat_dir_entry*) buf; ++ count = buf_size / sizeof(struct vfat_dir_entry); ++ dbg("expected entries 0x%x", count); ++ ++ fnlen = get_fat_attr_volume_id(filename, sizeof(filename), direntry, count); ++ if (fnlen > 0) ++ break; ++ ++ /* get FAT entry */ ++ fat_entry_off = (reserved * sector_size) + (next * sizeof(uint32_t)); ++ buf = volume_id_get_buffer(id, off + fat_entry_off, buf_size); ++ if (buf == NULL) ++ goto found; ++ ++ /* set next cluster */ ++ next = le32_to_cpu(*((uint32_t *) buf)) & 0x0fffffff; ++ if (next < 2 || next >= 0x0ffffff0) ++ break; ++ } ++ if (maxloop == 0) ++ dbg("reached maximum follow count of root cluster chain, give up"); ++ ++ vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (vs == NULL) ++ return -1; ++ ++ if (fnlen > 0 && memcmp((char*)filename, "NO NAME ", 11) != 0) { ++ volume_id_set_label_raw(id, filename, fnlen); ++ volume_id_set_label_string(id, filename, fnlen); ++ } else if (memcmp((char*)vs->type.fat32.label, "NO NAME ", 11) != 0) { ++ volume_id_set_label_raw(id, vs->type.fat32.label, 11); ++ volume_id_set_label_string(id, vs->type.fat32.label, 11); ++ } ++ volume_id_set_uuid(id, vs->type.fat32.serno, 0, UUID_DOS); ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "vfat"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/gfs.c' +--- grub-0.97.orig/libvolume_id/gfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/gfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,115 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Red Hat, Inc. <redhat.com> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++/* Common gfs/gfs2 constants: */ ++#define GFS_MAGIC 0x01161970 ++#define GFS_DEFAULT_BSIZE 4096 ++#define GFS_SUPERBLOCK_OFFSET (0x10 * GFS_DEFAULT_BSIZE) ++#define GFS_METATYPE_SB 1 ++#define GFS_FORMAT_SB 100 ++#define GFS_LOCKNAME_LEN 64 ++ ++/* gfs1 constants: */ ++#define GFS_FORMAT_FS 1309 ++#define GFS_FORMAT_MULTI 1401 ++/* gfs2 constants: */ ++#define GFS2_FORMAT_FS 1801 ++#define GFS2_FORMAT_MULTI 1900 ++ ++struct gfs2_meta_header { ++ uint32_t mh_magic; ++ uint32_t mh_type; ++ uint64_t __pad0; /* Was generation number in gfs1 */ ++ uint32_t mh_format; ++ uint32_t __pad1; /* Was incarnation number in gfs1 */ ++}; ++ ++struct gfs2_inum { ++ uint64_t no_formal_ino; ++ uint64_t no_addr; ++}; ++ ++struct gfs2_sb { ++ struct gfs2_meta_header sb_header; ++ ++ uint32_t sb_fs_format; ++ uint32_t sb_multihost_format; ++ uint32_t __pad0; /* Was superblock flags in gfs1 */ ++ ++ uint32_t sb_bsize; ++ uint32_t sb_bsize_shift; ++ uint32_t __pad1; /* Was journal segment size in gfs1 */ ++ ++ struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */ ++ struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */ ++ struct gfs2_inum sb_root_dir; ++ ++ char sb_lockproto[GFS_LOCKNAME_LEN]; ++ char sb_locktable[GFS_LOCKNAME_LEN]; ++ /* In gfs1, quota and license dinodes followed */ ++} PACKED; ++ ++static int volume_id_probe_gfs_generic(struct volume_id *id, uint64_t off, int vers) ++{ ++ struct gfs2_sb *sbd; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ sbd = (struct gfs2_sb *) ++ volume_id_get_buffer(id, off + GFS_SUPERBLOCK_OFFSET, sizeof(struct gfs2_sb)); ++ if (sbd == NULL) ++ return -1; ++ ++ if (be32_to_cpu(sbd->sb_header.mh_magic) == GFS_MAGIC && ++ be32_to_cpu(sbd->sb_header.mh_type) == GFS_METATYPE_SB && ++ be32_to_cpu(sbd->sb_header.mh_format) == GFS_FORMAT_SB) { ++ if (vers == 1) { ++ if (be32_to_cpu(sbd->sb_fs_format) != GFS_FORMAT_FS || ++ be32_to_cpu(sbd->sb_multihost_format) != GFS_FORMAT_MULTI) ++ return -1; /* not gfs1 */ ++ id->type = "gfs"; ++ } ++ else if (vers == 2) { ++ if (be32_to_cpu(sbd->sb_fs_format) != GFS2_FORMAT_FS || ++ be32_to_cpu(sbd->sb_multihost_format) != GFS2_FORMAT_MULTI) ++ return -1; /* not gfs2 */ ++ id->type = "gfs2"; ++ } ++ else ++ return -1; ++ strcpy(id->type_version, "1"); ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ return 0; ++ } ++ return -1; ++} ++ ++int volume_id_probe_gfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ return volume_id_probe_gfs_generic(id, off, 1); ++} ++ ++int volume_id_probe_gfs2(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ return volume_id_probe_gfs_generic(id, off, 2); ++} + +=== added file 'libvolume_id/hfs.c' +--- grub-0.97.orig/libvolume_id/hfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/hfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,318 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct hfs_finder_info{ ++ uint32_t boot_folder; ++ uint32_t start_app; ++ uint32_t open_folder; ++ uint32_t os9_folder; ++ uint32_t reserved; ++ uint32_t osx_folder; ++ uint8_t id[8]; ++} PACKED; ++ ++static struct hfs_mdb { ++ uint8_t signature[2]; ++ uint32_t cr_date; ++ uint32_t ls_Mod; ++ uint16_t atrb; ++ uint16_t nm_fls; ++ uint16_t vbm_st; ++ uint16_t alloc_ptr; ++ uint16_t nm_al_blks; ++ uint32_t al_blk_size; ++ uint32_t clp_size; ++ uint16_t al_bl_st; ++ uint32_t nxt_cnid; ++ uint16_t free_bks; ++ uint8_t label_len; ++ uint8_t label[27]; ++ uint32_t vol_bkup; ++ uint16_t vol_seq_num; ++ uint32_t wr_cnt; ++ uint32_t xt_clump_size; ++ uint32_t ct_clump_size; ++ uint16_t num_root_dirs; ++ uint32_t file_count; ++ uint32_t dir_count; ++ struct hfs_finder_info finder_info; ++ uint8_t embed_sig[2]; ++ uint16_t embed_startblock; ++ uint16_t embed_blockcount; ++} PACKED *hfs; ++ ++struct hfsplus_bnode_descriptor { ++ uint32_t next; ++ uint32_t prev; ++ uint8_t type; ++ uint8_t height; ++ uint16_t num_recs; ++ uint16_t reserved; ++} PACKED; ++ ++struct hfsplus_bheader_record { ++ uint16_t depth; ++ uint32_t root; ++ uint32_t leaf_count; ++ uint32_t leaf_head; ++ uint32_t leaf_tail; ++ uint16_t node_size; ++} PACKED; ++ ++struct hfsplus_catalog_key { ++ uint16_t key_len; ++ uint32_t parent_id; ++ uint16_t unicode_len; ++ uint8_t unicode[255 * 2]; ++} PACKED; ++ ++struct hfsplus_extent { ++ uint32_t start_block; ++ uint32_t block_count; ++} PACKED; ++ ++#define HFSPLUS_EXTENT_COUNT 8 ++struct hfsplus_fork { ++ uint64_t total_size; ++ uint32_t clump_size; ++ uint32_t total_blocks; ++ struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; ++} PACKED; ++ ++static struct hfsplus_vol_header { ++ uint8_t signature[2]; ++ uint16_t version; ++ uint32_t attributes; ++ uint32_t last_mount_vers; ++ uint32_t reserved; ++ uint32_t create_date; ++ uint32_t modify_date; ++ uint32_t backup_date; ++ uint32_t checked_date; ++ uint32_t file_count; ++ uint32_t folder_count; ++ uint32_t blocksize; ++ uint32_t total_blocks; ++ uint32_t free_blocks; ++ uint32_t next_alloc; ++ uint32_t rsrc_clump_sz; ++ uint32_t data_clump_sz; ++ uint32_t next_cnid; ++ uint32_t write_count; ++ uint64_t encodings_bmp; ++ struct hfs_finder_info finder_info; ++ struct hfsplus_fork alloc_file; ++ struct hfsplus_fork ext_file; ++ struct hfsplus_fork cat_file; ++ struct hfsplus_fork attr_file; ++ struct hfsplus_fork start_file; ++} PACKED *hfsplus; ++ ++#define HFS_SUPERBLOCK_OFFSET 0x400 ++#define HFS_NODE_LEAF 0xff ++#define HFSPLUS_POR_CNID 1 ++ ++static void hfsid_set_uuid(struct volume_id *id, const uint8_t *hfs_id) ++{ ++#if 0 ++ MD5_CTX md5c; ++ static const uint8_t hash_init[16] = { ++ 0xb3, 0xe2, 0x0f, 0x39, 0xf2, 0x92, 0x11, 0xd6, ++ 0x97, 0xa4, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac ++ }; ++ uint8_t uuid[16]; ++ ++ if (*((uint64_t *)hfs_id) == 0) ++ return; ++ ++ MD5_Init(&md5c); ++ MD5_Update(&md5c, &hash_init, 16); ++ MD5_Update(&md5c, hfs_id, 8); ++ MD5_Final(uuid, &md5c); ++ ++ uuid[6] = 0x30 | (uuid[6] & 0x0f); ++ uuid[8] = 0x80 | (uuid[8] & 0x3f); ++ volume_id_set_uuid(id, uuid, UUID_DCE); ++#endif ++ ++ volume_id_set_uuid(id, hfs_id, 0, UUID_64BIT_BE); ++} ++ ++int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ unsigned int blocksize; ++ unsigned int cat_block; ++ unsigned int ext_block_start; ++ unsigned int ext_block_count; ++ int ext; ++ unsigned int leaf_node_head; ++ unsigned int leaf_node_count; ++ unsigned int leaf_node_size; ++ unsigned int leaf_block; ++ uint64_t leaf_off; ++ unsigned int alloc_block_size; ++ unsigned int alloc_first_block; ++ unsigned int embed_first_block; ++ unsigned int record_count; ++ struct hfsplus_bnode_descriptor *descr; ++ struct hfsplus_bheader_record *bnode; ++ struct hfsplus_catalog_key *key; ++ unsigned int label_len; ++ struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; ++ const uint8_t *buf; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ hfs = (struct hfs_mdb *) buf; ++ if (memcmp((char *)hfs->signature, "BD", 2) != 0) ++ goto checkplus; ++ ++ /* it may be just a hfs wrapper for hfs+ */ ++ if (memcmp((char *)hfs->embed_sig, "H+", 2) == 0) { ++ alloc_block_size = be32_to_cpu(hfs->al_blk_size); ++ dbg("alloc_block_size 0x%x", alloc_block_size); ++ ++ alloc_first_block = be16_to_cpu(hfs->al_bl_st); ++ dbg("alloc_first_block 0x%x", alloc_first_block); ++ ++ embed_first_block = be16_to_cpu(hfs->embed_startblock); ++ dbg("embed_first_block 0x%x", embed_first_block); ++ ++ off += (alloc_first_block * 512) + ++ (embed_first_block * alloc_block_size); ++ dbg("hfs wrapped hfs+ found at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ goto checkplus; ++ } ++ ++ if (hfs->label_len > 0 && hfs->label_len < 28) { ++ volume_id_set_label_raw(id, hfs->label, hfs->label_len); ++ volume_id_set_label_string(id, hfs->label, hfs->label_len) ; ++ } ++ ++ hfsid_set_uuid(id, hfs->finder_info.id); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "hfs"; ++ ++ return 0; ++ ++checkplus: ++ hfsplus = (struct hfsplus_vol_header *) buf; ++ if (memcmp((char *)hfsplus->signature, "H+", 2) == 0) ++ goto hfsplus; ++ if (memcmp((char *)hfsplus->signature, "HX", 2) == 0) ++ goto hfsplus; ++ return -1; ++ ++hfsplus: ++ hfsid_set_uuid(id, hfsplus->finder_info.id); ++ ++ blocksize = be32_to_cpu(hfsplus->blocksize); ++ dbg("blocksize %u", blocksize); ++ ++ memcpy(extents, hfsplus->cat_file.extents, sizeof(extents)); ++ cat_block = be32_to_cpu(extents[0].start_block); ++ dbg("catalog start block 0x%x", cat_block); ++ ++ buf = volume_id_get_buffer(id, off + (cat_block * blocksize), 0x2000); ++ if (buf == NULL) ++ goto found; ++ ++ bnode = (struct hfsplus_bheader_record *) ++ &buf[sizeof(struct hfsplus_bnode_descriptor)]; ++ ++ leaf_node_head = be32_to_cpu(bnode->leaf_head); ++ dbg("catalog leaf node 0x%x", leaf_node_head); ++ ++ leaf_node_size = be16_to_cpu(bnode->node_size); ++ dbg("leaf node size 0x%x", leaf_node_size); ++ ++ leaf_node_count = be32_to_cpu(bnode->leaf_count); ++ dbg("leaf node count 0x%x", leaf_node_count); ++ if (leaf_node_count == 0) ++ goto found; ++ ++ leaf_block = (leaf_node_head * leaf_node_size) / blocksize; ++ ++ /* get physical location */ ++ for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) { ++ ext_block_start = be32_to_cpu(extents[ext].start_block); ++ ext_block_count = be32_to_cpu(extents[ext].block_count); ++ dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count); ++ ++ if (ext_block_count == 0) ++ goto found; ++ ++ /* this is our extent */ ++ if (leaf_block < ext_block_count) ++ break; ++ ++ leaf_block -= ext_block_count; ++ } ++ if (ext == HFSPLUS_EXTENT_COUNT) ++ goto found; ++ dbg("found block in extent %i", ext); ++ ++ leaf_off = (ext_block_start + leaf_block) * blocksize; ++ ++ buf = volume_id_get_buffer(id, off + leaf_off, leaf_node_size); ++ if (buf == NULL) ++ goto found; ++ ++ descr = (struct hfsplus_bnode_descriptor *) buf; ++ dbg("descriptor type 0x%x", descr->type); ++ ++ record_count = be16_to_cpu(descr->num_recs); ++ dbg("number of records %u", record_count); ++ if (record_count == 0) ++ goto found; ++ ++ if (descr->type != HFS_NODE_LEAF) ++ goto found; ++ ++ key = (struct hfsplus_catalog_key *) ++ &buf[sizeof(struct hfsplus_bnode_descriptor)]; ++ ++ dbg("parent id 0x%x", be32_to_cpu(key->parent_id)); ++ if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID) ++ goto found; ++ ++ label_len = be16_to_cpu(key->unicode_len) * 2; ++ dbg("label unicode16 len %i", label_len); ++ volume_id_set_label_raw(id, key->unicode, label_len); ++ volume_id_set_label_unicode16(id, key->unicode, BE, label_len); ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "hfsplus"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/highpoint.c' +--- grub-0.97.orig/libvolume_id/highpoint.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/highpoint.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,91 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct hpt37x_meta { ++ uint8_t filler1[32]; ++ uint32_t magic; ++} PACKED; ++ ++struct hpt45x_meta { ++ uint32_t magic; ++} PACKED; ++ ++#define HPT37X_CONFIG_OFF 0x1200 ++#define HPT37X_MAGIC_OK 0x5a7816f0 ++#define HPT37X_MAGIC_BAD 0x5a7816fd ++ ++#define HPT45X_MAGIC_OK 0x5a7816f3 ++#define HPT45X_MAGIC_BAD 0x5a7816fd ++ ++ ++int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct hpt37x_meta *hpt; ++ uint32_t magic; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ hpt = (struct hpt37x_meta *) buf; ++ magic = le32_to_cpu(hpt->magic); ++ if (magic != HPT37X_MAGIC_OK && magic != HPT37X_MAGIC_BAD) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "highpoint_raid_member"; ++ ++ return 0; ++} ++ ++int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct hpt45x_meta *hpt; ++ uint64_t meta_off; ++ uint32_t magic; ++ ++ dbg("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-11) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ hpt = (struct hpt45x_meta *) buf; ++ magic = le32_to_cpu(hpt->magic); ++ if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "highpoint_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/hpfs.c' +--- grub-0.97.orig/libvolume_id/hpfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/hpfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,51 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct hpfs_super ++{ ++ uint8_t magic[4]; ++ uint8_t version; ++} PACKED; ++ ++#define HPFS_SUPERBLOCK_OFFSET 0x2000 ++ ++int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct hpfs_super *hs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ hs = (struct hpfs_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x200); ++ if (hs == NULL) ++ return -1; ++ ++ if (memcmp((char *)hs->magic, "\x49\xe8\x95\xf9", 4) == 0) { ++ sprintf(id->type_version, "%u", hs->version); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "hpfs"; ++ return 0; ++ } ++ ++ return -1; ++} + +=== added file 'libvolume_id/iso9660.c' +--- grub-0.97.orig/libvolume_id/iso9660.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/iso9660.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,119 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define ISO_SUPERBLOCK_OFFSET 0x8000 ++#define ISO_SECTOR_SIZE 0x800 ++#define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE) ++#define ISO_VD_PRIMARY 0x1 ++#define ISO_VD_SUPPLEMENTARY 0x2 ++#define ISO_VD_END 0xff ++#define ISO_VD_MAX 16 ++ ++struct iso_volume_descriptor { ++ uint8_t type; ++ uint8_t id[5]; ++ uint8_t version; ++ uint8_t flags; ++ uint8_t system_id[32]; ++ uint8_t volume_id[32]; ++ uint8_t unused[8]; ++ uint8_t space_size[8]; ++ uint8_t escape_sequences[8]; ++} PACKED; ++ ++struct high_sierra_volume_descriptor { ++ uint8_t foo[8]; ++ uint8_t type; ++ uint8_t id[5]; ++ uint8_t version; ++} PACKED; ++ ++int volume_id_probe_iso9660(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint8_t *buf; ++ struct iso_volume_descriptor *is; ++ struct high_sierra_volume_descriptor *hs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ is = (struct iso_volume_descriptor *) buf; ++ ++ if (memcmp((char*)is->id, "CD001", 5) == 0) { ++ int vd_offset; ++ int i; ++ ++ dbg("read label from PVD"); ++ volume_id_set_label_raw(id, is->volume_id, 32); ++ volume_id_set_label_string(id, is->volume_id, 32); ++ ++ dbg("looking for SVDs"); ++ vd_offset = ISO_VD_OFFSET; ++ for (i = 0; i < ISO_VD_MAX; i++) { ++ uint8_t svd_label[64]; ++ ++ is = (struct iso_volume_descriptor *) volume_id_get_buffer(id, off + vd_offset, 0x200); ++ if (is == NULL || is->type == ISO_VD_END) ++ break; ++ if (is->type != ISO_VD_SUPPLEMENTARY) ++ continue; ++ ++ dbg("found SVD at offset 0x%llx", (unsigned long long) (off + vd_offset)); ++ if (memcmp((char *)is->escape_sequences, "%/@", 3) == 0|| ++ memcmp((char *)is->escape_sequences, "%/C", 3) == 0|| ++ memcmp((char *)is->escape_sequences, "%/E", 3) == 0) { ++ dbg("Joliet extension found"); ++ volume_id_set_unicode16(svd_label, sizeof(svd_label), is->volume_id, BE, 32); ++ if (memcmp((char *)id->label, (char *)svd_label, 16) == 0) { ++ dbg("SVD label is identical, use the possibly longer PVD one"); ++ break; ++ } ++ ++ volume_id_set_label_raw(id, is->volume_id, 32); ++ volume_id_set_label_string(id, svd_label, 32); ++ strcpy(id->type_version, "Joliet Extension"); ++ goto found; ++ } ++ vd_offset += ISO_SECTOR_SIZE; ++ } ++ goto found; ++ } ++ ++ hs = (struct high_sierra_volume_descriptor *) buf; ++ ++ if (memcmp((char *)hs->id, "CDROM", 5) == 0) { ++ strcpy(id->type_version, "High Sierra"); ++ goto found; ++ } ++ ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "iso9660"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/isw_raid.c' +--- grub-0.97.orig/libvolume_id/isw_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/isw_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,61 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct isw_meta { ++ uint8_t sig[32]; ++ uint32_t check_sum; ++ uint32_t mpb_size; ++ uint32_t family_num; ++ uint32_t generation_num; ++} PACKED; ++ ++#define ISW_SIGNATURE "Intel Raid ISM Cfg Sig. " ++ ++ ++int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct isw_meta *isw; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-2) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ isw = (struct isw_meta *) buf; ++ if (memcmp((char *)isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ memcpy(id->type_version, &isw->sig[sizeof(ISW_SIGNATURE)-1], 6); ++ id->type = "isw_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/jfs.c' +--- grub-0.97.orig/libvolume_id/jfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/jfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,60 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct jfs_super_block { ++ uint8_t magic[4]; ++ uint32_t version; ++ uint64_t size; ++ uint32_t bsize; ++ uint32_t dummy1; ++ uint32_t pbsize; ++ uint32_t dummy2[27]; ++ uint8_t uuid[16]; ++ uint8_t label[16]; ++ uint8_t loguuid[16]; ++} PACKED; ++ ++#define JFS_SUPERBLOCK_OFFSET 0x8000 ++ ++int volume_id_probe_jfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct jfs_super_block *js; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ js = (struct jfs_super_block *) volume_id_get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200); ++ if (js == NULL) ++ return -1; ++ ++ if (memcmp((char *)js->magic, "JFS1", 4) != 0) ++ return -1; ++ ++ volume_id_set_label_raw(id, js->label, 16); ++ volume_id_set_label_string(id, js->label, 16); ++ volume_id_set_uuid(id, js->uuid, 0, UUID_DCE); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "jfs"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/jmicron_raid.c' +--- grub-0.97.orig/libvolume_id/jmicron_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/jmicron_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,57 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct jmicron_meta { ++ int8_t signature[2]; ++ uint8_t minor_version; ++ uint8_t major_version; ++ uint16_t checksum; ++} PACKED; ++ ++int volume_id_probe_jmicron_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct jmicron_meta *jm; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ jm = (struct jmicron_meta *) buf; ++ if (memcmp((char *)jm->signature, "JM", 2) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u.%u", jm->major_version, jm->minor_version); ++ id->type = "jmicron_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/linux_raid.c' +--- grub-0.97.orig/libvolume_id/linux_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/linux_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,160 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++static struct mdp0_super_block { ++ uint32_t md_magic; ++ uint32_t major_version; ++ uint32_t minor_version; ++ uint32_t patch_version; ++ uint32_t gvalid_words; ++ uint32_t set_uuid0; ++ uint32_t ctime; ++ uint32_t level; ++ uint32_t size; ++ uint32_t nr_disks; ++ uint32_t raid_disks; ++ uint32_t md_minor; ++ uint32_t not_persistent; ++ uint32_t set_uuid1; ++ uint32_t set_uuid2; ++ uint32_t set_uuid3; ++} PACKED *mdp0; ++ ++struct mdp1_super_block { ++ uint32_t magic; ++ uint32_t major_version; ++ uint32_t feature_map; ++ uint32_t pad0; ++ uint8_t set_uuid[16]; ++ uint8_t set_name[32]; ++} PACKED *mdp1; ++ ++#define MD_RESERVED_BYTES 0x10000 ++#define MD_SB_MAGIC 0xa92b4efc ++ ++static int volume_id_probe_linux_raid0(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ union { ++ uint32_t ints[4]; ++ uint8_t bytes[16]; ++ } uuid; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ if (size < 0x10000) ++ return -1; ++ ++ buf = volume_id_get_buffer(id, off, 0x800); ++ if (buf == NULL) ++ return -1; ++ mdp0 = (struct mdp0_super_block *) buf; ++ ++ if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) { ++ uuid.ints[0] = bswap_32(mdp0->set_uuid0); ++ if (le32_to_cpu(mdp0->minor_version >= 90)) { ++ uuid.ints[1] = bswap_32(mdp0->set_uuid1); ++ uuid.ints[2] = bswap_32(mdp0->set_uuid2); ++ uuid.ints[3] = bswap_32(mdp0->set_uuid3); ++ } else { ++ uuid.ints[1] = 0; ++ uuid.ints[2] = 0; ++ uuid.ints[3] = 0; ++ } ++ volume_id_set_uuid(id, uuid.bytes, 0, UUID_FOURINT); ++ sprintf(id->type_version, "%u.%u.%u", ++ le32_to_cpu(mdp0->major_version), ++ le32_to_cpu(mdp0->minor_version), ++ le32_to_cpu(mdp0->patch_version)); ++ } else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) { ++ uuid.ints[0] = mdp0->set_uuid0; ++ if (be32_to_cpu(mdp0->minor_version >= 90)) { ++ uuid.ints[1] = mdp0->set_uuid1; ++ uuid.ints[2] = mdp0->set_uuid2; ++ uuid.ints[3] = mdp0->set_uuid3; ++ } else { ++ uuid.ints[1] = 0; ++ uuid.ints[2] = 0; ++ uuid.ints[3] = 0; ++ } ++ volume_id_set_uuid(id, uuid.bytes, 0, UUID_FOURINT); ++ sprintf(id->type_version, "%u.%u.%u", ++ be32_to_cpu(mdp0->major_version), ++ be32_to_cpu(mdp0->minor_version), ++ be32_to_cpu(mdp0->patch_version)); ++ } else ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "linux_raid_member"; ++ return 0; ++} ++ ++static int volume_id_probe_linux_raid1(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ buf = volume_id_get_buffer(id, off, 0x800); ++ if (buf == NULL) ++ return -1; ++ mdp1 = (struct mdp1_super_block *) buf; ++ ++ if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC) ++ return -1; ++ ++ volume_id_set_uuid(id, mdp1->set_uuid, 0, UUID_FOURINT); ++ volume_id_set_label_raw(id, mdp1->set_name, 32); ++ volume_id_set_label_string(id, mdp1->set_name, 32); ++ sprintf(id->type_version, "%u", le32_to_cpu(mdp1->major_version)); ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "linux_raid_member"; ++ return 0; ++} ++ ++int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint64_t sboff; ++ ++ /* version 0 at the end of the device */ ++ sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES; ++ if (volume_id_probe_linux_raid0(id, off + sboff, size) == 0) ++ return 0; ++ ++ /* version 1.0 at the end of the device */ ++ sboff = (size & ~(0x1000 - 1)) - 0x2000; ++ if (volume_id_probe_linux_raid1(id, off + sboff, size) == 0) ++ return 0; ++ ++ /* version 1.1 at the start of the device */ ++ if (volume_id_probe_linux_raid1(id, off, size) == 0) ++ return 0; ++ ++ /* version 1.2 at 4k offset from the start */ ++ if (volume_id_probe_linux_raid1(id, off + 0x1000, size) == 0) ++ return 0; ++ ++ return -1; ++} + +=== added file 'libvolume_id/linux_swap.c' +--- grub-0.97.orig/libvolume_id/linux_swap.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/linux_swap.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,85 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct swap_header_v1_2 { ++ uint8_t bootbits[1024]; ++ uint32_t version; ++ uint32_t last_page; ++ uint32_t nr_badpages; ++ uint8_t uuid[16]; ++ uint8_t volume_name[16]; ++} PACKED; ++ ++#define LARGEST_PAGESIZE 0x4000 ++ ++int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ unsigned int page; ++ struct swap_header_v1_2 *sw; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ /* eek, the swap signature is at the end of the PAGE_SIZE */ ++ for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) { ++ buf = volume_id_get_buffer(id, off + page-10, 10); ++ if (buf == NULL) ++ return -1; ++ ++ if (memcmp((char *)buf, "SWAP-SPACE", 10) == 0) { ++ strcpy(id->type_version, "1"); ++ goto found; ++ } ++ ++ if (memcmp((char *)buf, "SWAPSPACE2", 10) == 0) { ++ id->type = "swap"; ++ strcpy(id->type_version, "2"); ++ goto found_label; ++ } ++ ++ if (memcmp((char *)buf, "S1SUSPEND", 9) == 0) { ++ id->type = "suspend"; ++ strcpy(id->type_version, "s1suspend"); ++ goto found_label; ++ } ++ ++ if (memcmp((char *)buf, "ULSUSPEND", 9) == 0) { ++ id->type = "suspend"; ++ strcpy(id->type_version, "ulsuspend"); ++ goto found_label; ++ } ++ } ++ return -1; ++ ++found_label: ++ sw = (struct swap_header_v1_2 *) volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2)); ++ if (sw != NULL) { ++ volume_id_set_label_raw(id, sw->volume_name, 16); ++ volume_id_set_label_string(id, sw->volume_name, 16); ++ volume_id_set_uuid(id, sw->uuid, 0, UUID_DCE); ++ } ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_OTHER); ++ return 0; ++} + +=== added file 'libvolume_id/lsi_raid.c' +--- grub-0.97.orig/libvolume_id/lsi_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/lsi_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,55 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct lsi_meta { ++ uint8_t sig[6]; ++} PACKED; ++ ++#define LSI_SIGNATURE "$XIDE$" ++ ++int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct lsi_meta *lsi; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ lsi = (struct lsi_meta *) buf; ++ if (memcmp((char *)lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "lsi_mega_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/luks.c' +--- grub-0.97.orig/libvolume_id/luks.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/luks.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,76 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 W. Michael Petullo <mike@flyn.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define LUKS_SECTOR_SHIFT 9 ++#define LUKS_SECTOR_SIZE (1 << LUKS_SECTOR_SHIFT) ++ ++#define LUKS_CIPHERNAME_L 32 ++#define LUKS_CIPHERMODE_L 32 ++#define LUKS_HASHSPEC_L 32 ++#define LUKS_DIGESTSIZE 20 ++#define LUKS_SALTSIZE 32 ++#define LUKS_NUMKEYS 8 ++ ++#define LUKS_MAGIC_L 6 ++#define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/LUKS_SECTOR_SIZE+1) ++#define UUID_STRING_L 40 ++static const uint8_t LUKS_MAGIC[] = {'L','U','K','S', 0xba, 0xbe}; ++ ++struct luks_phdr { ++ uint8_t magic[LUKS_MAGIC_L]; ++ uint16_t version; ++ uint8_t cipherName[LUKS_CIPHERNAME_L]; ++ uint8_t cipherMode[LUKS_CIPHERMODE_L]; ++ uint8_t hashSpec[LUKS_HASHSPEC_L]; ++ uint32_t payloadOffset; ++ uint32_t keyBytes; ++ uint8_t mkDigest[LUKS_DIGESTSIZE]; ++ uint8_t mkDigestSalt[LUKS_SALTSIZE]; ++ uint32_t mkDigestIterations; ++ uint8_t uuid[UUID_STRING_L]; ++ struct { ++ uint32_t active; ++ uint32_t passwordIterations; ++ uint8_t passwordSalt[LUKS_SALTSIZE]; ++ uint32_t keyMaterialOffset; ++ uint32_t stripes; ++ } keyblock[LUKS_NUMKEYS]; ++}; ++ ++int volume_id_probe_luks(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct luks_phdr *header; ++ ++ header = (struct luks_phdr*) volume_id_get_buffer(id, off, LUKS_PHDR_SIZE); ++ if (header == NULL) ++ return -1; ++ ++ if (memcmp((char *)header->magic, (char *)LUKS_MAGIC, LUKS_MAGIC_L)) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_CRYPTO); ++ volume_id_set_uuid(id, header->uuid, 36, UUID_HEX_STRING); ++ sprintf(id->type_version, "%u", le16_to_cpu(header->version)); ++ id->type = "crypto_LUKS"; ++ return 0; ++} + +=== added file 'libvolume_id/lvm.c' +--- grub-0.97.orig/libvolume_id/lvm.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/lvm.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,92 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct lvm1_super_block { ++ uint8_t id[2]; ++} PACKED; ++ ++struct lvm2_super_block { ++ uint8_t id[8]; ++ uint64_t sector_xl; ++ uint32_t crc_xl; ++ uint32_t offset_xl; ++ uint8_t type[8]; ++} PACKED; ++ ++#define LVM1_SB_OFF 0x400 ++#define LVM1_MAGIC "HM" ++ ++int volume_id_probe_lvm1(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct lvm1_super_block *lvm; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + LVM1_SB_OFF, 0x800); ++ if (buf == NULL) ++ return -1; ++ ++ lvm = (struct lvm1_super_block *) buf; ++ ++ if (memcmp((char *)lvm->id, LVM1_MAGIC, 2) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "LVM1_member"; ++ ++ return 0; ++} ++ ++#define LVM2_LABEL_ID "LABELONE" ++#define LVM2LABEL_SCAN_SECTORS 4 ++ ++int volume_id_probe_lvm2(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ unsigned int soff; ++ struct lvm2_super_block *lvm; ++ ++ dbg("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off, LVM2LABEL_SCAN_SECTORS * 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ ++ for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) { ++ lvm = (struct lvm2_super_block *) &buf[soff]; ++ ++ if (memcmp((char *)lvm->id, LVM2_LABEL_ID, 8) == 0) ++ goto found; ++ } ++ ++ return -1; ++ ++found: ++ memcpy(id->type_version, lvm->type, 8); ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "LVM2_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/minix.c' +--- grub-0.97.orig/libvolume_id/minix.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/minix.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,112 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define MINIX_SUPERBLOCK_OFFSET 0x400 ++ ++#define MINIX_SUPER_MAGIC 0x137F ++#define MINIX_SUPER_MAGIC2 0x138F ++#define MINIX2_SUPER_MAGIC 0x2468 ++#define MINIX2_SUPER_MAGIC2 0x2478 ++#define MINIX3_SUPER_MAGIC 0x4d5a ++ ++struct minix_super_block ++{ ++ uint16_t s_ninodes; ++ uint16_t s_nzones; ++ uint16_t s_imap_blocks; ++ uint16_t s_zmap_blocks; ++ uint16_t s_firstdatazone; ++ uint16_t s_log_zone_size; ++ uint32_t s_max_size; ++ uint16_t s_magic; ++ uint16_t s_state; ++ uint32_t s_zones; ++} PACKED; ++ ++struct minix3_super_block { ++ uint32_t s_ninodes; ++ uint16_t s_pad0; ++ uint16_t s_imap_blocks; ++ uint16_t s_zmap_blocks; ++ uint16_t s_firstdatazone; ++ uint16_t s_log_zone_size; ++ uint16_t s_pad1; ++ uint32_t s_max_size; ++ uint32_t s_zones; ++ uint16_t s_magic; ++ uint16_t s_pad2; ++ uint16_t s_blocksize; ++ uint8_t s_disk_version; ++} PACKED; ++ ++int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint8_t *buf; ++ struct minix_super_block *ms; ++ struct minix3_super_block *m3s; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + MINIX_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ ms = (struct minix_super_block *) buf; ++ ++ if (ms->s_magic == MINIX_SUPER_MAGIC || ++ ms->s_magic == bswap_16(MINIX_SUPER_MAGIC)) { ++ strcpy(id->type_version, "1"); ++ goto found; ++ } ++ if (ms->s_magic == MINIX_SUPER_MAGIC2 || ++ ms->s_magic == bswap_16(MINIX_SUPER_MAGIC2)) { ++ strcpy(id->type_version, "1"); ++ goto found; ++ } ++ if (ms->s_magic == MINIX2_SUPER_MAGIC || ++ ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC)) { ++ strcpy(id->type_version, "2"); ++ goto found; ++ } ++ if (ms->s_magic == MINIX2_SUPER_MAGIC2 || ++ ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC2)) { ++ strcpy(id->type_version, "2"); ++ goto found; ++ } ++ ++ m3s = (struct minix3_super_block *) buf; ++ if (m3s->s_magic == MINIX3_SUPER_MAGIC || ++ m3s->s_magic == bswap_16(MINIX3_SUPER_MAGIC)) { ++ strcpy(id->type_version, "3"); ++ goto found; ++ } ++ goto exit; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "minix"; ++ return 0; ++ ++exit: ++ return -1; ++} + +=== added file 'libvolume_id/misc.c' +--- grub-0.97.orig/libvolume_id/misc.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/misc.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,34 @@ ++/* ++ * volume_id/misc.c ++ * ++ * Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++#define _GNU_SOURCE ++#include <string.h> ++ ++/* ++ * Misc auxiliary functions required for volume_id inside grub ++ */ ++size_t strnlen(const char *s, size_t limit) ++{ ++ size_t length = 0; ++ while ( (length < limit) && (*s++) ) ++ length++; ++ ++ return length; ++} ++ ++char *strchr (const char *s, int c) ++{ ++ do { ++ if ( *s == c ) { ++ return (char*)s; ++ } ++ } while ( *s++ ); ++ ++ return 0; ++} + +=== added file 'libvolume_id/netware.c' +--- grub-0.97.orig/libvolume_id/netware.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/netware.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,98 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define NW_SUPERBLOCK_OFFSET 0x1000 ++ ++struct netware_super_block { ++ uint8_t SBH_Signature[4]; ++ uint16_t SBH_VersionMajor; ++ uint16_t SBH_VersionMinor; ++ uint16_t SBH_VersionMediaMajor; ++ uint16_t SBH_VersionMediaMinor; ++ uint32_t SBH_ItemsMoved; ++ uint8_t SBH_InternalID[16]; ++ uint32_t SBH_PackedSize; ++ uint32_t SBH_Checksum; ++ uint32_t supersyncid; ++ int64_t superlocation[4]; ++ uint32_t physSizeUsed; ++ uint32_t sizeUsed; ++ uint32_t superTimeStamp; ++ uint32_t reserved0[1]; ++ int64_t SBH_LoggedPoolDataBlk; ++ int64_t SBH_PoolDataBlk; ++ uint8_t SBH_OldInternalID[16]; ++ uint32_t SBH_PoolToLVStartUTC; ++ uint32_t SBH_PoolToLVEndUTC; ++ uint16_t SBH_VersionMediaMajorCreate; ++ uint16_t SBH_VersionMediaMinorCreate; ++ uint32_t SBH_BlocksMoved; ++ uint32_t SBH_TempBTSpBlk; ++ uint32_t SBH_TempFTSpBlk; ++ uint32_t SBH_TempFTSpBlk1; ++ uint32_t SBH_TempFTSpBlk2; ++ uint32_t nssMagicNumber; ++ uint32_t poolClassID; ++ uint32_t poolID; ++ uint32_t createTime; ++ int64_t SBH_LoggedVolumeDataBlk; ++ int64_t SBH_VolumeDataBlk; ++ int64_t SBH_SystemBeastBlkNum; ++ uint64_t totalblocks; ++ uint16_t SBH_Name[64]; ++ uint8_t SBH_VolumeID[16]; ++ uint8_t SBH_PoolID[16]; ++ uint8_t SBH_PoolInternalID[16]; ++ uint64_t SBH_Lsn; ++ uint32_t SBH_SS_Enabled; ++ uint32_t SBH_SS_CreateTime; ++ uint8_t SBH_SS_OriginalPoolID[16]; ++ uint8_t SBH_SS_OriginalVolumeID[16]; ++ uint8_t SBH_SS_Guid[16]; ++ uint16_t SBH_SS_OriginalName[64]; ++ uint32_t reserved2[64-(2+46)]; ++} PACKED; ++ ++int volume_id_probe_netware(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct netware_super_block *nw; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ nw = (struct netware_super_block *) volume_id_get_buffer(id, off + NW_SUPERBLOCK_OFFSET, 0x200); ++ if (nw == NULL) ++ return -1; ++ ++ if (memcmp((char *)nw->SBH_Signature, "SPB5", 4) != 0) ++ return -1; ++ ++ volume_id_set_uuid(id, nw->SBH_PoolID, 0, UUID_DCE); ++ ++ sprintf(id->type_version, "%u.%02u", ++ le16_to_cpu(nw->SBH_VersionMediaMajor), le16_to_cpu(nw->SBH_VersionMediaMinor)); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "nss"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/ntfs.c' +--- grub-0.97.orig/libvolume_id/ntfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ntfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,192 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++static struct ntfs_super_block { ++ uint8_t jump[3]; ++ uint8_t oem_id[8]; ++ uint16_t bytes_per_sector; ++ uint8_t sectors_per_cluster; ++ uint16_t reserved_sectors; ++ uint8_t fats; ++ uint16_t root_entries; ++ uint16_t sectors; ++ uint8_t media_type; ++ uint16_t sectors_per_fat; ++ uint16_t sectors_per_track; ++ uint16_t heads; ++ uint32_t hidden_sectors; ++ uint32_t large_sectors; ++ uint16_t unused[2]; ++ uint64_t number_of_sectors; ++ uint64_t mft_cluster_location; ++ uint64_t mft_mirror_cluster_location; ++ int8_t cluster_per_mft_record; ++ uint8_t reserved1[3]; ++ int8_t cluster_per_index_record; ++ uint8_t reserved2[3]; ++ uint8_t volume_serial[8]; ++ uint16_t checksum; ++} PACKED *ns; ++ ++static struct master_file_table_record { ++ uint8_t magic[4]; ++ uint16_t usa_ofs; ++ uint16_t usa_count; ++ uint64_t lsn; ++ uint16_t sequence_number; ++ uint16_t link_count; ++ uint16_t attrs_offset; ++ uint16_t flags; ++ uint32_t bytes_in_use; ++ uint32_t bytes_allocated; ++} PACKED *mftr; ++ ++static struct file_attribute { ++ uint32_t type; ++ uint32_t len; ++ uint8_t non_resident; ++ uint8_t name_len; ++ uint16_t name_offset; ++ uint16_t flags; ++ uint16_t instance; ++ uint32_t value_len; ++ uint16_t value_offset; ++} PACKED *attr; ++ ++static struct volume_info { ++ uint64_t reserved; ++ uint8_t major_ver; ++ uint8_t minor_ver; ++} PACKED *info; ++ ++#define MFT_RECORD_VOLUME 3 ++#define MFT_RECORD_ATTR_VOLUME_NAME 0x60 ++#define MFT_RECORD_ATTR_VOLUME_INFO 0x70 ++#define MFT_RECORD_ATTR_OBJECT_ID 0x40 ++#define MFT_RECORD_ATTR_END 0xffffffffu ++ ++#undef debug ++#define debug grub_printf ++ ++int volume_id_probe_ntfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ unsigned int sector_size; ++ unsigned int cluster_size; ++ uint64_t mft_cluster; ++ uint64_t mft_off; ++ unsigned int mft_record_size; ++ unsigned int attr_type; ++ unsigned int attr_off; ++ unsigned int attr_len; ++ unsigned int val_off; ++ unsigned int val_len; ++ const uint8_t *buf; ++ const uint8_t *val; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ ns = (struct ntfs_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (ns == NULL) ++ return -1; ++ ++ if (memcmp((char *)ns->oem_id, "NTFS", 4) != 0) ++ return -1; ++ ++ volume_id_set_uuid(id, ns->volume_serial, 0, UUID_64BIT_LE); ++ ++ sector_size = le16_to_cpu(ns->bytes_per_sector); ++ if (sector_size < 0x200) ++ return -1; ++ ++ cluster_size = ns->sectors_per_cluster * sector_size; ++ mft_cluster = le64_to_cpu(ns->mft_cluster_location); ++ mft_off = mft_cluster * cluster_size; ++ ++ if (ns->cluster_per_mft_record < 0) ++ /* size = -log2(mft_record_size); normally 1024 Bytes */ ++ mft_record_size = 1 << -ns->cluster_per_mft_record; ++ else ++ mft_record_size = ns->cluster_per_mft_record * cluster_size; ++ ++ dbg("sectorsize 0x%x", sector_size); ++ dbg("clustersize 0x%x", cluster_size); ++ dbg("mftcluster %llu", (unsigned long long) mft_cluster); ++ dbg("mftoffset 0x%llx", (unsigned long long) mft_off); ++ dbg("cluster per mft_record %i", ns->cluster_per_mft_record); ++ dbg("mft record size %i", mft_record_size); ++ ++ buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size), ++ mft_record_size); ++ if (buf == NULL) ++ return -1; ++ ++ mftr = (struct master_file_table_record*) buf; ++ dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]); ++ if (memcmp((char *)mftr->magic, "FILE", 4) != 0) ++ return -1; ++ ++ attr_off = le16_to_cpu(mftr->attrs_offset); ++ dbg("file $Volume's attributes are at offset %i", attr_off); ++ ++ while (1) { ++ attr = (struct file_attribute*) &buf[attr_off]; ++ attr_type = le32_to_cpu(attr->type); ++ attr_len = le16_to_cpu(attr->len); ++ val_off = le16_to_cpu(attr->value_offset); ++ val_len = le32_to_cpu(attr->value_len); ++ attr_off += attr_len; ++ ++ if (attr_len == 0) ++ break; ++ ++ if (attr_off >= mft_record_size) ++ break; ++ ++ if (attr_type == MFT_RECORD_ATTR_END) ++ break; ++ ++ dbg("found attribute type 0x%x, len %i, at offset %i", ++ attr_type, attr_len, attr_off); ++ ++ if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) { ++ dbg("found info, len %i", val_len); ++ info = (struct volume_info*) (((uint8_t *) attr) + val_off); ++ sprintf(id->type_version, "%u.%u", info->major_ver, info->minor_ver); ++ } ++ ++ if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) { ++ dbg("found label, len %i", val_len); ++ if (val_len > VOLUME_ID_LABEL_SIZE) ++ val_len = VOLUME_ID_LABEL_SIZE; ++ ++ val = ((uint8_t *) attr) + val_off; ++ volume_id_set_label_raw(id, val, val_len); ++ volume_id_set_label_unicode16(id, val, LE, val_len); ++ } ++ } ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "ntfs"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/nvidia_raid.c' +--- grub-0.97.orig/libvolume_id/nvidia_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/nvidia_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,59 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct nvidia_meta { ++ uint8_t vendor[8]; ++ uint32_t size; ++ uint32_t chksum; ++ uint16_t version; ++} PACKED; ++ ++#define NVIDIA_SIGNATURE "NVIDIA" ++ ++int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct nvidia_meta *nv; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-2) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ nv = (struct nvidia_meta *) buf; ++ if (memcmp((char *)nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u", le16_to_cpu(nv->version)); ++ id->type = "nvidia_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/ocfs.c' +--- grub-0.97.orig/libvolume_id/ocfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ocfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,186 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Andre Masella <andre@masella.no-ip.org> ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct ocfs1_super_block_header { ++ uint32_t minor_version; ++ uint32_t major_version; ++ uint8_t signature[128]; ++ uint8_t mount_point[128]; ++ uint64_t serial_num; ++ uint64_t device_size; ++ uint64_t start_off; ++ uint64_t bitmap_off; ++ uint64_t publ_off; ++ uint64_t vote_off; ++ uint64_t root_bitmap_off; ++ uint64_t data_start_off; ++ uint64_t root_bitmap_size; ++ uint64_t root_off; ++ uint64_t root_size; ++ uint64_t cluster_size; ++ uint64_t num_nodes; ++ uint64_t num_clusters; ++ uint64_t dir_node_size; ++ uint64_t file_node_size; ++ uint64_t internal_off; ++ uint64_t node_cfg_off; ++ uint64_t node_cfg_size; ++ uint64_t new_cfg_off; ++ uint32_t prot_bits; ++ int32_t excl_mount; ++} PACKED; ++ ++struct ocfs1_super_block_label { ++ struct ocfs1_disk_lock { ++ uint32_t curr_master; ++ uint8_t file_lock; ++ uint8_t compat_pad[3]; ++ uint64_t last_write_time; ++ uint64_t last_read_time; ++ uint32_t writer_node_num; ++ uint32_t reader_node_num; ++ uint64_t oin_node_map; ++ uint64_t dlock_seq_num; ++ } PACKED disk_lock; ++ uint8_t label[64]; ++ uint16_t label_len; ++ uint8_t vol_id[16]; ++ uint16_t vol_id_len; ++ uint8_t cluster_name[64]; ++ uint16_t cluster_name_len; ++} PACKED; ++ ++struct ocfs2_super_block { ++ uint8_t i_signature[8]; ++ uint32_t i_generation; ++ int16_t i_suballoc_slot; ++ uint16_t i_suballoc_bit; ++ uint32_t i_reserved0; ++ uint32_t i_clusters; ++ uint32_t i_uid; ++ uint32_t i_gid; ++ uint64_t i_size; ++ uint16_t i_mode; ++ uint16_t i_links_count; ++ uint32_t i_flags; ++ uint64_t i_atime; ++ uint64_t i_ctime; ++ uint64_t i_mtime; ++ uint64_t i_dtime; ++ uint64_t i_blkno; ++ uint64_t i_last_eb_blk; ++ uint32_t i_fs_generation; ++ uint32_t i_atime_nsec; ++ uint32_t i_ctime_nsec; ++ uint32_t i_mtime_nsec; ++ uint64_t i_reserved1[9]; ++ uint64_t i_pad1; ++ uint16_t s_major_rev_level; ++ uint16_t s_minor_rev_level; ++ uint16_t s_mnt_count; ++ int16_t s_max_mnt_count; ++ uint16_t s_state; ++ uint16_t s_errors; ++ uint32_t s_checkinterval; ++ uint64_t s_lastcheck; ++ uint32_t s_creator_os; ++ uint32_t s_feature_compat; ++ uint32_t s_feature_incompat; ++ uint32_t s_feature_ro_compat; ++ uint64_t s_root_blkno; ++ uint64_t s_system_dir_blkno; ++ uint32_t s_blocksize_bits; ++ uint32_t s_clustersize_bits; ++ uint16_t s_max_slots; ++ uint16_t s_reserved1; ++ uint32_t s_reserved2; ++ uint64_t s_first_cluster_group; ++ uint8_t s_label[64]; ++ uint8_t s_uuid[16]; ++} PACKED; ++ ++int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct ocfs1_super_block_header *osh; ++ struct ocfs1_super_block_label *osl; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ osh = (struct ocfs1_super_block_header *) buf; ++ if (memcmp((char *)osh->signature, "OracleCFS", 9) != 0) ++ return -1; ++ sprintf(id->type_version, "%u.%u", osh->major_version, osh->minor_version); ++ ++ dbg("found OracleCFS signature, now reading label"); ++ buf = volume_id_get_buffer(id, off + 0x200, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ osl = (struct ocfs1_super_block_label *) buf; ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ if (osl->label_len <= 64) { ++ volume_id_set_label_raw(id, osl->label, 64); ++ volume_id_set_label_string(id, osl->label, 64); ++ } ++ if (osl->vol_id_len == 16) ++ volume_id_set_uuid(id, osl->vol_id, 0, UUID_DCE); ++ id->type = "ocfs"; ++ return 0; ++} ++ ++#define OCFS2_MAX_BLOCKSIZE 0x1000 ++#define OCFS2_SUPER_BLOCK_BLKNO 2 ++ ++int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct ocfs2_super_block *os; ++ size_t blksize; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ for (blksize = 0x200; blksize <= OCFS2_MAX_BLOCKSIZE; blksize <<= 1) { ++ buf = volume_id_get_buffer(id, off + OCFS2_SUPER_BLOCK_BLKNO * blksize, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ os = (struct ocfs2_super_block *) buf; ++ if (memcmp((char *)os->i_signature, "OCFSV2", 6) != 0) ++ continue; ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ volume_id_set_label_raw(id, os->s_label, 64); ++ volume_id_set_label_string(id, os->s_label, 64); ++ volume_id_set_uuid(id, os->s_uuid, 0, UUID_DCE); ++ sprintf(id->type_version, "%u.%u", os->s_major_rev_level, os->s_minor_rev_level); ++ id->type = "ocfs2"; ++ return 0; ++ } ++ return -1; ++} + +=== added file 'libvolume_id/promise_raid.c' +--- grub-0.97.orig/libvolume_id/promise_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/promise_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,65 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct promise_meta { ++ uint8_t sig[24]; ++} PACKED; ++ ++#define PDC_CONFIG_OFF 0x1200 ++#define PDC_SIGNATURE "Promise Technology, Inc." ++ ++int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ struct promise_meta *pdc; ++ unsigned int i; ++ static unsigned int sectors[] = { ++ 63, 255, 256, 16, 399, 0 ++ }; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x40000) ++ return -1; ++ ++ for (i = 0; sectors[i] != 0; i++) { ++ uint64_t meta_off; ++ ++ meta_off = ((size / 0x200) - sectors[i]) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ pdc = (struct promise_meta *) buf; ++ if (memcmp((char *)pdc->sig, PDC_SIGNATURE, sizeof(PDC_SIGNATURE)-1) == 0) ++ goto found; ++ } ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ id->type = "promise_fasttrack_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/reiserfs.c' +--- grub-0.97.orig/libvolume_id/reiserfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/reiserfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,113 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Copyright (C) 2005 Tobias Klauser <tklauser@access.unizh.ch> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct reiserfs_super_block { ++ uint32_t blocks_count; ++ uint32_t free_blocks; ++ uint32_t root_block; ++ uint32_t journal_block; ++ uint32_t journal_dev; ++ uint32_t orig_journal_size; ++ uint32_t dummy2[5]; ++ uint16_t blocksize; ++ uint16_t dummy3[3]; ++ uint8_t magic[12]; ++ uint32_t dummy4[5]; ++ uint8_t uuid[16]; ++ uint8_t label[16]; ++} PACKED; ++ ++struct reiser4_super_block { ++ uint8_t magic[16]; ++ uint16_t dummy[2]; ++ uint8_t uuid[16]; ++ uint8_t label[16]; ++ uint64_t dummy2; ++} PACKED; ++ ++#define REISERFS1_SUPERBLOCK_OFFSET 0x2000 ++#define REISERFS_SUPERBLOCK_OFFSET 0x10000 ++ ++int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct reiserfs_super_block *rs; ++ struct reiser4_super_block *rs4; ++ uint8_t *buf; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ buf = volume_id_get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ rs = (struct reiserfs_super_block *) buf; ++ if (memcmp((char *)rs->magic, "ReIsErFs", 8) == 0) { ++ strcpy(id->type_version, "3.5"); ++ id->type = "reiserfs"; ++ goto found; ++ } ++ if (memcmp((char *)rs->magic, "ReIsEr2Fs", 9) == 0) { ++ strcpy(id->type_version, "3.6"); ++ id->type = "reiserfs"; ++ goto found_label; ++ } ++ if (memcmp((char *)rs->magic, "ReIsEr3Fs", 9) == 0) { ++ strcpy(id->type_version, "JR"); ++ id->type = "reiserfs"; ++ goto found_label; ++ } ++ ++ rs4 = (struct reiser4_super_block *) buf; ++ if (memcmp((char *)rs4->magic, "ReIsEr4", 7) == 0) { ++ strcpy(id->type_version, "4"); ++ volume_id_set_label_raw(id, rs4->label, 16); ++ volume_id_set_label_string(id, rs4->label, 16); ++ volume_id_set_uuid(id, rs4->uuid, 0, UUID_DCE); ++ id->type = "reiser4"; ++ goto found; ++ } ++ ++ buf = volume_id_get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ rs = (struct reiserfs_super_block *) buf; ++ if (memcmp((char *)rs->magic, "ReIsErFs", 8) == 0) { ++ strcpy(id->type_version, "3.5"); ++ id->type = "reiserfs"; ++ goto found; ++ } ++ ++ return -1; ++ ++found_label: ++ volume_id_set_label_raw(id, rs->label, 16); ++ volume_id_set_label_string(id, rs->label, 16); ++ volume_id_set_uuid(id, rs->uuid, 0, UUID_DCE); ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ ++ return 0; ++} + +=== added file 'libvolume_id/romfs.c' +--- grub-0.97.orig/libvolume_id/romfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/romfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,55 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct romfs_super { ++ uint8_t magic[8]; ++ uint32_t size; ++ uint32_t checksum; ++ uint8_t name[0]; ++} PACKED; ++ ++int volume_id_probe_romfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct romfs_super *rfs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ rfs = (struct romfs_super *) volume_id_get_buffer(id, off, 0x200); ++ if (rfs == NULL) ++ return -1; ++ ++ if (memcmp((char *)rfs->magic, "-rom1fs-", 4) == 0) { ++ size_t len = strlen((char *)rfs->name); ++ ++ if (len) { ++ volume_id_set_label_raw(id, rfs->name, len); ++ volume_id_set_label_string(id, rfs->name, len); ++ } ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "romfs"; ++ return 0; ++ } ++ ++ return -1; ++} + +=== added file 'libvolume_id/silicon_raid.c' +--- grub-0.97.orig/libvolume_id/silicon_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/silicon_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,71 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct silicon_meta { ++ uint8_t unknown0[0x2E]; ++ uint8_t ascii_version[0x36 - 0x2E]; ++ uint8_t diskname[0x56 - 0x36]; ++ uint8_t unknown1[0x60 - 0x56]; ++ uint32_t magic; ++ uint32_t unknown1a[0x6C - 0x64]; ++ uint32_t array_sectors_low; ++ uint32_t array_sectors_high; ++ uint8_t unknown2[0x78 - 0x74]; ++ uint32_t thisdisk_sectors; ++ uint8_t unknown3[0x100 - 0x7C]; ++ uint8_t unknown4[0x104 - 0x100]; ++ uint16_t product_id; ++ uint16_t vendor_id; ++ uint16_t minor_ver; ++ uint16_t major_ver; ++} PACKED; ++ ++#define SILICON_MAGIC 0x2F000000 ++ ++int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct silicon_meta *sil; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ sil = (struct silicon_meta *) buf; ++ if (le32_to_cpu(sil->magic) != SILICON_MAGIC) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u.%u", le16_to_cpu(sil->major_ver), le16_to_cpu(sil->minor_ver)); ++ id->type = "silicon_medley_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/squashfs.c' +--- grub-0.97.orig/libvolume_id/squashfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/squashfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,63 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define SQUASHFS_MAGIC 0x73717368 ++ ++struct squashfs_super { ++ uint32_t s_magic; ++ uint32_t inodes; ++ uint32_t bytes_used_2; ++ uint32_t uid_start_2; ++ uint32_t guid_start_2; ++ uint32_t inode_table_start_2; ++ uint32_t directory_table_start_2; ++ uint16_t s_major; ++ uint16_t s_minor; ++} PACKED; ++ ++int volume_id_probe_squashfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct squashfs_super *sqs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ sqs = (struct squashfs_super *) volume_id_get_buffer(id, off, 0x200); ++ if (sqs == NULL) ++ return -1; ++ ++ if (sqs->s_magic == SQUASHFS_MAGIC) { ++ sprintf(id->type_version, "%u.%u", sqs->s_major, sqs->s_minor); ++ goto found; ++ } ++ if (sqs->s_magic == bswap_32(SQUASHFS_MAGIC)) { ++ sprintf(id->type_version, "%u.%u", bswap_16(sqs->s_major), bswap_16(sqs->s_minor)); ++ goto found; ++ } ++ ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "squashfs"; ++ return 0; ++} + +=== added file 'libvolume_id/strfuncs.h' +--- grub-0.97.orig/libvolume_id/strfuncs.h 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/strfuncs.h 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,5 @@ ++ ++#include <stdlib.h> ++ ++size_t strnlen(const char *s, size_t limit); ++char *strchr (const char *s, int c); + +=== added file 'libvolume_id/sysv.c' +--- grub-0.97.orig/libvolume_id/sysv.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/sysv.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,128 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define SYSV_NICINOD 100 ++#define SYSV_NICFREE 50 ++ ++struct sysv_super ++{ ++ uint16_t s_isize; ++ uint16_t s_pad0; ++ uint32_t s_fsize; ++ uint16_t s_nfree; ++ uint16_t s_pad1; ++ uint32_t s_free[SYSV_NICFREE]; ++ uint16_t s_ninode; ++ uint16_t s_pad2; ++ uint16_t s_inode[SYSV_NICINOD]; ++ uint8_t s_flock; ++ uint8_t s_ilock; ++ uint8_t s_fmod; ++ uint8_t s_ronly; ++ uint32_t s_time; ++ uint16_t s_dinfo[4]; ++ uint32_t s_tfree; ++ uint16_t s_tinode; ++ uint16_t s_pad3; ++ uint8_t s_fname[6]; ++ uint8_t s_fpack[6]; ++ uint32_t s_fill[12]; ++ uint32_t s_state; ++ uint32_t s_magic; ++ uint32_t s_type; ++} PACKED; ++ ++#define XENIX_NICINOD 100 ++#define XENIX_NICFREE 100 ++ ++struct xenix_super { ++ uint16_t s_isize; ++ uint32_t s_fsize; ++ uint16_t s_nfree; ++ uint32_t s_free[XENIX_NICFREE]; ++ uint16_t s_ninode; ++ uint16_t s_inode[XENIX_NICINOD]; ++ uint8_t s_flock; ++ uint8_t s_ilock; ++ uint8_t s_fmod; ++ uint8_t s_ronly; ++ uint32_t s_time; ++ uint32_t s_tfree; ++ uint16_t s_tinode; ++ uint16_t s_dinfo[4]; ++ uint8_t s_fname[6]; ++ uint8_t s_fpack[6]; ++ uint8_t s_clean; ++ uint8_t s_fill[371]; ++ uint32_t s_magic; ++ uint32_t s_type; ++} PACKED; ++ ++#define SYSV_SUPERBLOCK_BLOCK 0x01 ++#define SYSV_MAGIC 0xfd187e20 ++#define XENIX_SUPERBLOCK_BLOCK 0x18 ++#define XENIX_MAGIC 0x2b5544 ++#define SYSV_MAX_BLOCKSIZE 0x800 ++ ++int volume_id_probe_sysv(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct sysv_super *vs; ++ struct xenix_super *xs; ++ unsigned int boff; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) { ++ vs = (struct sysv_super *) ++ volume_id_get_buffer(id, off + (boff * SYSV_SUPERBLOCK_BLOCK), 0x200); ++ if (vs == NULL) ++ return -1; ++ ++ if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) { ++ volume_id_set_label_raw(id, vs->s_fname, 6); ++ volume_id_set_label_string(id, vs->s_fname, 6); ++ id->type = "sysv"; ++ goto found; ++ } ++ } ++ ++ for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) { ++ xs = (struct xenix_super *) ++ volume_id_get_buffer(id, off + (boff + XENIX_SUPERBLOCK_BLOCK), 0x200); ++ if (xs == NULL) ++ return -1; ++ ++ if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) { ++ volume_id_set_label_raw(id, xs->s_fname, 6); ++ volume_id_set_label_string(id, xs->s_fname, 6); ++ id->type = "xenix"; ++ goto found; ++ } ++ } ++ ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ return 0; ++} + +=== added file 'libvolume_id/udf.c' +--- grub-0.97.orig/libvolume_id/udf.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/udf.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,173 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct volume_descriptor { ++ struct descriptor_tag { ++ uint16_t id; ++ uint16_t version; ++ uint8_t checksum; ++ uint8_t reserved; ++ uint16_t serial; ++ uint16_t crc; ++ uint16_t crc_len; ++ uint32_t location; ++ } PACKED tag; ++ union { ++ struct anchor_descriptor { ++ uint32_t length; ++ uint32_t location; ++ } PACKED anchor; ++ struct primary_descriptor { ++ uint32_t seq_num; ++ uint32_t desc_num; ++ struct dstring { ++ uint8_t clen; ++ uint8_t c[31]; ++ } PACKED ident; ++ } PACKED primary; ++ } PACKED type; ++} PACKED; ++ ++struct volume_structure_descriptor { ++ uint8_t type; ++ uint8_t id[5]; ++ uint8_t version; ++} PACKED; ++ ++#define UDF_VSD_OFFSET 0x8000 ++ ++int volume_id_probe_udf(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct volume_descriptor *vd; ++ struct volume_structure_descriptor *vsd; ++ unsigned int bs; ++ unsigned int b; ++ unsigned int type; ++ unsigned int count; ++ unsigned int loc; ++ unsigned int clen; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET, 0x200); ++ if (vsd == NULL) ++ return -1; ++ ++ if (memcmp((char *)vsd->id, "NSR02", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "NSR03", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "BEA01", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "BOOT2", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "CD001", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "CDW02", 5) == 0) ++ goto blocksize; ++ if (memcmp((char *)vsd->id, "TEA03", 5) == 0) ++ goto blocksize; ++ return -1; ++ ++blocksize: ++ /* search the next VSD to get the logical block size of the volume */ ++ for (bs = 0x800; bs < 0x8000; bs += 0x800) { ++ vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800); ++ if (vsd == NULL) ++ return -1; ++ dbg("test for blocksize: 0x%x", bs); ++ if (vsd->id[0] != '\0') ++ goto nsr; ++ } ++ return -1; ++ ++nsr: ++ /* search the list of VSDs for a NSR descriptor */ ++ for (b = 0; b < 64; b++) { ++ vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800); ++ if (vsd == NULL) ++ return -1; ++ ++ dbg("vsd: %c%c%c%c%c", ++ vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]); ++ ++ if (vsd->id[0] == '\0') ++ return -1; ++ if (memcmp((char *)vsd->id, "NSR02", 5) == 0) ++ goto anchor; ++ if (memcmp((char *)vsd->id, "NSR03", 5) == 0) ++ goto anchor; ++ } ++ return -1; ++ ++anchor: ++ /* read anchor volume descriptor */ ++ vd = (struct volume_descriptor *) volume_id_get_buffer(id, off + (256 * bs), 0x200); ++ if (vd == NULL) ++ return -1; ++ ++ type = le16_to_cpu(vd->tag.id); ++ if (type != 2) /* TAG_ID_AVDP */ ++ goto found; ++ ++ /* get desriptor list address and block count */ ++ count = le32_to_cpu(vd->type.anchor.length) / bs; ++ loc = le32_to_cpu(vd->type.anchor.location); ++ dbg("0x%x descriptors starting at logical secor 0x%x", count, loc); ++ ++ /* pick the primary descriptor from the list */ ++ for (b = 0; b < count; b++) { ++ vd = (struct volume_descriptor *) volume_id_get_buffer(id, off + ((loc + b) * bs), 0x200); ++ if (vd == NULL) ++ return -1; ++ ++ type = le16_to_cpu(vd->tag.id); ++ dbg("descriptor type %i", type); ++ ++ /* check validity */ ++ if (type == 0) ++ goto found; ++ if (le32_to_cpu(vd->tag.location) != loc + b) ++ goto found; ++ ++ if (type == 1) /* TAG_ID_PVD */ ++ goto pvd; ++ } ++ goto found; ++ ++pvd: ++ volume_id_set_label_raw(id, &(vd->type.primary.ident.clen), 32); ++ ++ clen = vd->type.primary.ident.clen; ++ dbg("label string charsize=%i bit", clen); ++ if (clen == 8) ++ volume_id_set_label_string(id, vd->type.primary.ident.c, 31); ++ else if (clen == 16) ++ volume_id_set_label_unicode16(id, vd->type.primary.ident.c, BE,31); ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "udf"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/ufs.c' +--- grub-0.97.orig/libvolume_id/ufs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/ufs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,217 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct ufs_super_block { ++ uint32_t fs_link; ++ uint32_t fs_rlink; ++ uint32_t fs_sblkno; ++ uint32_t fs_cblkno; ++ uint32_t fs_iblkno; ++ uint32_t fs_dblkno; ++ uint32_t fs_cgoffset; ++ uint32_t fs_cgmask; ++ uint32_t fs_time; ++ uint32_t fs_size; ++ uint32_t fs_dsize; ++ uint32_t fs_ncg; ++ uint32_t fs_bsize; ++ uint32_t fs_fsize; ++ uint32_t fs_frag; ++ uint32_t fs_minfree; ++ uint32_t fs_rotdelay; ++ uint32_t fs_rps; ++ uint32_t fs_bmask; ++ uint32_t fs_fmask; ++ uint32_t fs_bshift; ++ uint32_t fs_fshift; ++ uint32_t fs_maxcontig; ++ uint32_t fs_maxbpg; ++ uint32_t fs_fragshift; ++ uint32_t fs_fsbtodb; ++ uint32_t fs_sbsize; ++ uint32_t fs_csmask; ++ uint32_t fs_csshift; ++ uint32_t fs_nindir; ++ uint32_t fs_inopb; ++ uint32_t fs_nspf; ++ uint32_t fs_optim; ++ uint32_t fs_npsect_state; ++ uint32_t fs_interleave; ++ uint32_t fs_trackskew; ++ uint32_t fs_id[2]; ++ uint32_t fs_csaddr; ++ uint32_t fs_cssize; ++ uint32_t fs_cgsize; ++ uint32_t fs_ntrak; ++ uint32_t fs_nsect; ++ uint32_t fs_spc; ++ uint32_t fs_ncyl; ++ uint32_t fs_cpg; ++ uint32_t fs_ipg; ++ uint32_t fs_fpg; ++ struct ufs_csum { ++ uint32_t cs_ndir; ++ uint32_t cs_nbfree; ++ uint32_t cs_nifree; ++ uint32_t cs_nffree; ++ } PACKED fs_cstotal; ++ int8_t fs_fmod; ++ int8_t fs_clean; ++ int8_t fs_ronly; ++ int8_t fs_flags; ++ union { ++ struct { ++ int8_t fs_fsmnt[512]; ++ uint32_t fs_cgrotor; ++ uint32_t fs_csp[31]; ++ uint32_t fs_maxcluster; ++ uint32_t fs_cpc; ++ uint16_t fs_opostbl[16][8]; ++ } PACKED fs_u1; ++ struct { ++ int8_t fs_fsmnt[468]; ++ uint8_t fs_volname[32]; ++ uint64_t fs_swuid; ++ int32_t fs_pad; ++ uint32_t fs_cgrotor; ++ uint32_t fs_ocsp[28]; ++ uint32_t fs_contigdirs; ++ uint32_t fs_csp; ++ uint32_t fs_maxcluster; ++ uint32_t fs_active; ++ int32_t fs_old_cpc; ++ int32_t fs_maxbsize; ++ int64_t fs_sparecon64[17]; ++ int64_t fs_sblockloc; ++ struct ufs2_csum_total { ++ uint64_t cs_ndir; ++ uint64_t cs_nbfree; ++ uint64_t cs_nifree; ++ uint64_t cs_nffree; ++ uint64_t cs_numclusters; ++ uint64_t cs_spare[3]; ++ } PACKED fs_cstotal; ++ struct ufs_timeval { ++ int32_t tv_sec; ++ int32_t tv_usec; ++ } PACKED fs_time; ++ int64_t fs_size; ++ int64_t fs_dsize; ++ uint64_t fs_csaddr; ++ int64_t fs_pendingblocks; ++ int32_t fs_pendinginodes; ++ } PACKED fs_u2; ++ } fs_u11; ++ union { ++ struct { ++ int32_t fs_sparecon[53]; ++ int32_t fs_reclaim; ++ int32_t fs_sparecon2[1]; ++ int32_t fs_state; ++ uint32_t fs_qbmask[2]; ++ uint32_t fs_qfmask[2]; ++ } PACKED fs_sun; ++ struct { ++ int32_t fs_sparecon[53]; ++ int32_t fs_reclaim; ++ int32_t fs_sparecon2[1]; ++ uint32_t fs_npsect; ++ uint32_t fs_qbmask[2]; ++ uint32_t fs_qfmask[2]; ++ } PACKED fs_sunx86; ++ struct { ++ int32_t fs_sparecon[50]; ++ int32_t fs_contigsumsize; ++ int32_t fs_maxsymlinklen; ++ int32_t fs_inodefmt; ++ uint32_t fs_maxfilesize[2]; ++ uint32_t fs_qbmask[2]; ++ uint32_t fs_qfmask[2]; ++ int32_t fs_state; ++ } PACKED fs_44; ++ } fs_u2; ++ int32_t fs_postblformat; ++ int32_t fs_nrpos; ++ int32_t fs_postbloff; ++ int32_t fs_rotbloff; ++ uint32_t fs_magic; ++ uint8_t fs_space[1]; ++} PACKED; ++ ++#define UFS_MAGIC 0x00011954 ++#define UFS2_MAGIC 0x19540119 ++#define UFS_MAGIC_FEA 0x00195612 ++#define UFS_MAGIC_LFN 0x00095014 ++ ++int volume_id_probe_ufs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ uint32_t magic; ++ int i; ++ struct ufs_super_block *ufs; ++ int offsets[] = {0, 8, 64, 256, -1}; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ for (i = 0; offsets[i] >= 0; i++) { ++ ufs = (struct ufs_super_block *) volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800); ++ if (ufs == NULL) ++ return -1; ++ ++ dbg("offset 0x%x", offsets[i] * 0x400); ++ magic = be32_to_cpu(ufs->fs_magic); ++ if ((magic == UFS_MAGIC) || ++ (magic == UFS2_MAGIC) || ++ (magic == UFS_MAGIC_FEA) || ++ (magic == UFS_MAGIC_LFN)) { ++ dbg("magic 0x%08x(be)", magic); ++ goto found; ++ } ++ magic = le32_to_cpu(ufs->fs_magic); ++ if ((magic == UFS_MAGIC) || ++ (magic == UFS2_MAGIC) || ++ (magic == UFS_MAGIC_FEA) || ++ (magic == UFS_MAGIC_LFN)) { ++ dbg("magic 0x%08x(le)", magic); ++ goto found; ++ } ++ } ++ return -1; ++ ++found: ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "ufs"; ++ switch (magic) { ++ case UFS_MAGIC: ++ strcpy(id->type_version, "1"); ++ break; ++ case UFS2_MAGIC: ++ strcpy(id->type_version, "2"); ++ volume_id_set_label_raw(id, ufs->fs_u11.fs_u2.fs_volname, 32); ++ volume_id_set_label_string(id, ufs->fs_u11.fs_u2.fs_volname, 32); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} + +=== added file 'libvolume_id/util.c' +--- grub-0.97.orig/libvolume_id/util.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/util.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,472 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include <stdlib.h> ++ ++#include "strfuncs.h" ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++static char hex[] = "0123456789abcdef"; ++ ++#define hexhi(val) hex[val >> 4] ++#define hexlo(val) hex[val & 0xf] ++ ++/* count of characters used to encode one unicode char */ ++static int utf8_encoded_expected_len(const char *str) ++{ ++ unsigned char c = (unsigned char)str[0]; ++ ++ if (c < 0x80) ++ return 1; ++ if ((c & 0xe0) == 0xc0) ++ return 2; ++ if ((c & 0xf0) == 0xe0) ++ return 3; ++ if ((c & 0xf8) == 0xf0) ++ return 4; ++ if ((c & 0xfc) == 0xf8) ++ return 5; ++ if ((c & 0xfe) == 0xfc) ++ return 6; ++ return 0; ++} ++ ++/* decode one unicode char */ ++static int utf8_encoded_to_unichar(const char *str) ++{ ++ int unichar; ++ int len; ++ int i; ++ ++ len = utf8_encoded_expected_len(str); ++ switch (len) { ++ case 1: ++ return (int)str[0]; ++ case 2: ++ unichar = str[0] & 0x1f; ++ break; ++ case 3: ++ unichar = (int)str[0] & 0x0f; ++ break; ++ case 4: ++ unichar = (int)str[0] & 0x07; ++ break; ++ case 5: ++ unichar = (int)str[0] & 0x03; ++ break; ++ case 6: ++ unichar = (int)str[0] & 0x01; ++ break; ++ default: ++ return -1; ++ } ++ ++ for (i = 1; i < len; i++) { ++ if (((int)str[i] & 0xc0) != 0x80) ++ return -1; ++ unichar <<= 6; ++ unichar |= (int)str[i] & 0x3f; ++ } ++ ++ return unichar; ++} ++ ++/* expected size used to encode one unicode char */ ++static int utf8_unichar_to_encoded_len(int unichar) ++{ ++ if (unichar < 0x80) ++ return 1; ++ if (unichar < 0x800) ++ return 2; ++ if (unichar < 0x10000) ++ return 3; ++ if (unichar < 0x200000) ++ return 4; ++ if (unichar < 0x4000000) ++ return 5; ++ return 6; ++} ++ ++/* check if unicode char has a valid numeric range */ ++static int utf8_unichar_valid_range(int unichar) ++{ ++ if (unichar > 0x10ffff) ++ return 0; ++ if ((unichar & 0xfffff800) == 0xd800) ++ return 0; ++ if ((unichar > 0xfdcf) && (unichar < 0xfdf0)) ++ return 0; ++ if ((unichar & 0xffff) == 0xffff) ++ return 0; ++ return 1; ++} ++ ++/* validate one encoded unicode char and return its length */ ++int volume_id_utf8_encoded_valid_unichar(const char *str) ++{ ++ int len; ++ int unichar; ++ int i; ++ ++ len = utf8_encoded_expected_len(str); ++ if (len == 0) ++ return -1; ++ ++ /* ascii is valid */ ++ if (len == 1) ++ return 1; ++ ++ /* check if expected encoded chars are available */ ++ for (i = 0; i < len; i++) ++ if ((str[i] & 0x80) != 0x80) ++ return -1; ++ ++ unichar = utf8_encoded_to_unichar(str); ++ ++ /* check if encoded length matches encoded value */ ++ if (utf8_unichar_to_encoded_len(unichar) != len) ++ return -1; ++ ++ /* check if value has valid range */ ++ if (!utf8_unichar_valid_range(unichar)) ++ return -1; ++ ++ return len; ++} ++ ++size_t volume_id_set_unicode16(uint8_t *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count) ++{ ++ size_t i, j; ++ uint16_t c; ++ ++ j = 0; ++ for (i = 0; i + 2 <= count; i += 2) { ++ if (endianess == LE) ++ c = (buf[i+1] << 8) | buf[i]; ++ else ++ c = (buf[i] << 8) | buf[i+1]; ++ if (c == 0) { ++ str[j] = '\0'; ++ break; ++ } else if (c < 0x80) { ++ if (j+1 >= len) ++ break; ++ str[j++] = (uint8_t) c; ++ } else if (c < 0x800) { ++ if (j+2 >= len) ++ break; ++ str[j++] = (uint8_t) (0xc0 | (c >> 6)); ++ str[j++] = (uint8_t) (0x80 | (c & 0x3f)); ++ } else { ++ if (j+3 >= len) ++ break; ++ str[j++] = (uint8_t) (0xe0 | (c >> 12)); ++ str[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f)); ++ str[j++] = (uint8_t) (0x80 | (c & 0x3f)); ++ } ++ } ++ str[j] = '\0'; ++ return j; ++} ++ ++static char *usage_to_string(enum volume_id_usage usage_id) ++{ ++ switch (usage_id) { ++ case VOLUME_ID_FILESYSTEM: ++ return "filesystem"; ++ case VOLUME_ID_OTHER: ++ return "other"; ++ case VOLUME_ID_RAID: ++ return "raid"; ++ case VOLUME_ID_DISKLABEL: ++ return "disklabel"; ++ case VOLUME_ID_CRYPTO: ++ return "crypto"; ++ case VOLUME_ID_UNPROBED: ++ return "unprobed"; ++ case VOLUME_ID_UNUSED: ++ return "unused"; ++ } ++ return NULL; ++} ++ ++void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id) ++{ ++ id->usage_id = usage_id; ++ id->usage = usage_to_string(usage_id); ++} ++ ++void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count) ++{ ++ if (count > sizeof(id->label)) ++ count = sizeof(id->label); ++ ++ memcpy(id->label_raw, buf, count); ++ id->label_raw_len = count; ++} ++ ++void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count) ++{ ++ size_t i; ++ ++ if (count >= sizeof(id->label)) ++ count = sizeof(id->label)-1; ++ ++ memcpy(id->label, buf, count); ++ id->label[count] = '\0'; ++ ++ /* remove trailing whitespace */ ++ i = strnlen(id->label, count); ++ while (i--) { ++ if (!isspace(id->label[i])) ++ break; ++ } ++ id->label[i+1] = '\0'; ++} ++ ++void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count) ++{ ++ if (count >= sizeof(id->label)) ++ count = sizeof(id->label)-1; ++ ++ volume_id_set_unicode16((uint8_t *)id->label, sizeof(id->label), buf, endianess, count); ++} ++ ++void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format) ++{ ++ unsigned int i; ++ unsigned int count = 0; ++ char *uuid; ++ ++ if (len > sizeof(id->uuid_raw)) ++ len = sizeof(id->uuid_raw); ++ ++ switch(format) { ++ case UUID_STRING: ++ count = len; ++ break; ++ case UUID_HEX_STRING: ++ count = len; ++ break; ++ case UUID_DOS: ++ count = 4; ++ break; ++ case UUID_64BIT_LE: ++ case UUID_64BIT_BE: ++ count = 8; ++ break; ++ case UUID_DCE: ++ count = 16; ++ break; ++ case UUID_FOURINT: ++ count = 35; ++ break; ++ } ++ memcpy(id->uuid_raw, buf, count); ++ id->uuid_raw_len = count; ++ ++ /* if set, create string in the same format, the native platform uses */ ++ for (i = 0; i < count; i++) ++ if (buf[i] != 0) ++ goto set; ++ return; ++ ++set: ++ uuid = id->uuid; ++ switch(format) { ++ case UUID_DOS: ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid = '\0'; ++ break; ++ case UUID_64BIT_LE: ++ *uuid++ = hexhi(buf[7]); ++ *uuid++ = hexlo(buf[7]); ++ *uuid++ = hexhi(buf[6]); ++ *uuid++ = hexlo(buf[6]); ++ *uuid++ = hexhi(buf[5]); ++ *uuid++ = hexlo(buf[5]); ++ *uuid++ = hexhi(buf[4]); ++ *uuid++ = hexlo(buf[4]); ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid = '\0'; ++ break; ++ case UUID_64BIT_BE: ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = hexhi(buf[4]); ++ *uuid++ = hexlo(buf[4]); ++ *uuid++ = hexhi(buf[5]); ++ *uuid++ = hexlo(buf[5]); ++ *uuid++ = hexhi(buf[6]); ++ *uuid++ = hexlo(buf[6]); ++ *uuid++ = hexhi(buf[7]); ++ *uuid++ = hexlo(buf[7]); ++ *uuid = '\0'; ++ break; ++ case UUID_DCE: ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[4]); ++ *uuid++ = hexlo(buf[4]); ++ *uuid++ = hexhi(buf[5]); ++ *uuid++ = hexlo(buf[5]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[6]); ++ *uuid++ = hexlo(buf[6]); ++ *uuid++ = hexhi(buf[7]); ++ *uuid++ = hexlo(buf[7]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[8]); ++ *uuid++ = hexlo(buf[8]); ++ *uuid++ = hexhi(buf[9]); ++ *uuid++ = hexlo(buf[9]); ++ *uuid++ = '-'; ++ *uuid++ = hexhi(buf[10]); ++ *uuid++ = hexlo(buf[10]); ++ *uuid++ = hexhi(buf[11]); ++ *uuid++ = hexlo(buf[11]); ++ *uuid++ = hexhi(buf[12]); ++ *uuid++ = hexlo(buf[12]); ++ *uuid++ = hexhi(buf[13]); ++ *uuid++ = hexlo(buf[13]); ++ *uuid++ = hexhi(buf[14]); ++ *uuid++ = hexlo(buf[14]); ++ *uuid++ = hexhi(buf[15]); ++ *uuid++ = hexlo(buf[15]); ++ *uuid = '\0'; ++ break; ++ case UUID_HEX_STRING: ++ /* translate A..F to a..f */ ++ memcpy(id->uuid, buf, count); ++ for (i = 0; i < count; i++) ++ if (id->uuid[i] >= 'A' && id->uuid[i] <= 'F') ++ id->uuid[i] = (id->uuid[i] - 'A') + 'a'; ++ id->uuid[count] = '\0'; ++ break; ++ case UUID_STRING: ++ memcpy(id->uuid, buf, count); ++ id->uuid[count] = '\0'; ++ break; ++ case UUID_FOURINT: ++ *uuid++ = hexhi(buf[0]); ++ *uuid++ = hexlo(buf[0]); ++ *uuid++ = hexhi(buf[1]); ++ *uuid++ = hexlo(buf[1]); ++ *uuid++ = hexhi(buf[2]); ++ *uuid++ = hexlo(buf[2]); ++ *uuid++ = hexhi(buf[3]); ++ *uuid++ = hexlo(buf[3]); ++ *uuid++ = ':'; ++ *uuid++ = hexhi(buf[4]); ++ *uuid++ = hexlo(buf[4]); ++ *uuid++ = hexhi(buf[5]); ++ *uuid++ = hexlo(buf[5]); ++ *uuid++ = hexhi(buf[6]); ++ *uuid++ = hexlo(buf[6]); ++ *uuid++ = hexhi(buf[7]); ++ *uuid++ = hexlo(buf[7]); ++ *uuid++ = ':'; ++ *uuid++ = hexhi(buf[8]); ++ *uuid++ = hexlo(buf[8]); ++ *uuid++ = hexhi(buf[9]); ++ *uuid++ = hexlo(buf[9]); ++ *uuid++ = hexhi(buf[10]); ++ *uuid++ = hexlo(buf[10]); ++ *uuid++ = hexhi(buf[11]); ++ *uuid++ = hexlo(buf[11]); ++ *uuid++ = ':'; ++ *uuid++ = hexhi(buf[12]); ++ *uuid++ = hexlo(buf[12]); ++ *uuid++ = hexhi(buf[13]); ++ *uuid++ = hexlo(buf[13]); ++ *uuid++ = hexhi(buf[14]); ++ *uuid++ = hexlo(buf[14]); ++ *uuid++ = hexhi(buf[15]); ++ *uuid++ = hexlo(buf[15]); ++ *uuid = '\0'; ++ break; ++ default: ++ *uuid = '\0'; ++ break; ++ } ++} ++ ++uint8_t *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len) ++{ ++ info("get buffer off 0x%llx(%llu), len 0x%zx", (unsigned long long) off, (unsigned long long) off, len); ++ /* check if requested area fits in superblock buffer */ ++ if (off + len <= SB_BUFFER_SIZE) { ++ /* check if we need to read */ ++ if ((off + len) > id->sbbuf_len) { ++ if (devread (0, 0, off + len, (char*)id->sbbuf) == 0) ++ { ++ return NULL; ++ } ++ id->sbbuf_len = off + len; ++ } ++ return &(id->sbbuf[off]); ++ } else { ++ if (len > SEEK_BUFFER_SIZE) { ++ dbg("seek buffer too small %d", SEEK_BUFFER_SIZE); ++ return NULL; ++ } ++ ++ /* check if we need to read */ ++ if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) { ++ info("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len); ++ if (devread(off >> 9, off & 0x1ff, len, (char*)id->seekbuf) == 0) ++ { ++ return NULL; ++ } ++ id->seekbuf_off = off; ++ id->seekbuf_len = len; ++ } ++ return &(id->seekbuf[off - id->seekbuf_off]); ++ } ++} + +=== added file 'libvolume_id/util.h' +--- grub-0.97.orig/libvolume_id/util.h 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/util.h 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,98 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005-2006 Kay Sievers <kay.sievers@vrfy.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _VOLUME_ID_UTIL_ ++#define _VOLUME_ID_UTIL_ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include <endian.h> ++#include <byteswap.h> ++#include <syslog.h> ++ ++#define ALLOWED_CHARS "#+-.:=@_" ++ ++#ifndef PACKED ++#define PACKED __attribute__((packed)) ++#endif ++ ++#define err(format, arg...) volume_id_log_fn(LOG_ERR, __FILE__, __LINE__, format, ##arg) ++#ifdef INFO ++#define info(format, arg...) volume_id_log_fn(LOG_INFO, __FILE__, __LINE__, format, ##arg) ++#else ++#define info(format, arg...) do { } while (0) ++#endif ++ ++#ifdef DEBUG ++#define dbg(format, arg...) volume_id_log_fn(LOG_DEBUG, __FILE__, __LINE__, format, ##arg) ++#else ++#define dbg(format, arg...) do { } while (0) ++#endif ++ ++/* size of superblock buffer, reiserfs block is at 64k */ ++#define SB_BUFFER_SIZE 0x11000 ++/* size of seek buffer, FAT cluster is 32k max */ ++#define SEEK_BUFFER_SIZE 0x10000 ++ ++#ifdef __BYTE_ORDER ++#if (__BYTE_ORDER == __LITTLE_ENDIAN) ++#define le16_to_cpu(x) (x) ++#define le32_to_cpu(x) (x) ++#define le64_to_cpu(x) (x) ++#define be16_to_cpu(x) bswap_16(x) ++#define be32_to_cpu(x) bswap_32(x) ++#define cpu_to_le16(x) (x) ++#define cpu_to_le32(x) (x) ++#define cpu_to_be32(x) bswap_32(x) ++#elif (__BYTE_ORDER == __BIG_ENDIAN) ++#define le16_to_cpu(x) bswap_16(x) ++#define le32_to_cpu(x) bswap_32(x) ++#define le64_to_cpu(x) bswap_64(x) ++#define be16_to_cpu(x) (x) ++#define be32_to_cpu(x) (x) ++#define cpu_to_le16(x) bswap_16(x) ++#define cpu_to_le32(x) bswap_32(x) ++#define cpu_to_be32(x) (x) ++#endif ++#endif /* __BYTE_ORDER */ ++ ++enum uuid_format { ++ UUID_STRING, ++ UUID_HEX_STRING, ++ UUID_DCE, ++ UUID_DOS, ++ UUID_64BIT_LE, ++ UUID_64BIT_BE, ++ UUID_FOURINT, ++}; ++ ++enum endian { ++ LE = 0, ++ BE = 1 ++}; ++ ++extern int volume_id_utf8_encoded_valid_unichar(const char *str); ++extern size_t volume_id_set_unicode16(uint8_t *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count); ++extern void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id); ++extern void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count); ++extern void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count); ++extern void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count); ++extern void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format); ++extern uint8_t *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len); ++extern void volume_id_free_buffer(struct volume_id *id); ++ ++#endif /* _VOLUME_ID_UTIL_ */ ++ + +=== added file 'libvolume_id/via_raid.c' +--- grub-0.97.orig/libvolume_id/via_raid.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/via_raid.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,88 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * Based on information taken from dmraid: ++ * Copyright (C) 2004-2006 Heinz Mauelshagen, Red Hat GmbH ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct via_meta { ++ uint16_t signature; ++ uint8_t version_number; ++ struct via_array { ++ uint16_t disk_bit_mask; ++ uint8_t disk_array_ex; ++ uint32_t capacity_low; ++ uint32_t capacity_high; ++ uint32_t serial_checksum; ++ } PACKED array; ++ uint32_t serial_checksum[8]; ++ uint8_t checksum; ++} PACKED; ++ ++#define VIA_SIGNATURE 0xAA55 ++ ++/* 8 bit checksum on first 50 bytes of metadata. */ ++static uint8_t meta_checksum(struct via_meta *via) ++{ ++ uint8_t i = 50, sum = 0; ++ ++ while (i--) ++ sum += ((uint8_t*) via)[i]; ++ ++ return sum == via->checksum; ++} ++ ++ ++int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ const uint8_t *buf; ++ uint64_t meta_off; ++ struct via_meta *via; ++ ++ dbg("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ if (size < 0x10000) ++ return -1; ++ ++ meta_off = ((size / 0x200)-1) * 0x200; ++ ++ buf = volume_id_get_buffer(id, off + meta_off, 0x200); ++ if (buf == NULL) ++ return -1; ++ ++ via = (struct via_meta *) buf; ++ if (le16_to_cpu(via->signature) != VIA_SIGNATURE) ++ return -1; ++ ++ if (via->version_number > 1) ++ return -1; ++ ++ if (!meta_checksum(via)) ++ return -1; ++ ++ volume_id_set_usage(id, VOLUME_ID_RAID); ++ sprintf(id->type_version, "%u", via->version_number); ++ id->type = "via_raid_member"; ++ ++ return 0; ++} + +=== added file 'libvolume_id/volume_id.c' +--- grub-0.97.orig/libvolume_id/volume_id.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/volume_id.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,222 @@ ++/* ++ * volume_id - reads volume label and uuid ++ * ++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * Grub Port, Copyright (C) 2008 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include <fcntl.h> ++#include <sys/stat.h> ++ ++#include "volume_id.h" ++#include "util.h" ++#include "strfuncs.h" ++#include "shared.h" ++ ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++ ++struct prober { ++ volume_id_probe_fn_t prober; ++ const char *name[4]; ++}; ++ ++#define NOT_SUPPORTED(x) ++#define SUPPORTED(x) x ++ ++static const struct prober prober_raid[] = { ++ { volume_id_probe_ddf_raid, { "ddf_raid", } }, ++ ++ /* { volume_id_probe_linux_raid, { "linux_raid", } }, */ ++ /* { volume_id_probe_intel_software_raid, { "isw_raid", } }, */ ++ /* { volume_id_probe_lsi_mega_raid, { "lsi_mega_raid", } }, */ ++ /* { volume_id_probe_via_raid, { "via_raid", } }, */ ++ /* { volume_id_probe_silicon_medley_raid, { "silicon_medley_raid", } }, */ ++ /* { volume_id_probe_nvidia_raid, { "nvidia_raid", } }, */ ++ /* { volume_id_probe_promise_fasttrack_raid, { "promise_fasttrack_raid", } }, */ ++ /* { volume_id_probe_highpoint_45x_raid, { "highpoint_raid", } }, */ ++ /* { volume_id_probe_adaptec_raid, { "adaptec_raid", } }, */ ++ /* { volume_id_probe_jmicron_raid, { "jmicron_raid", } }, */ ++ /* { volume_id_probe_lvm1, { "lvm1", } }, */ ++ /* { volume_id_probe_lvm2, { "lvm2", } }, */ ++ /* { volume_id_probe_highpoint_37x_raid, { "highpoint_raid", } }, */ ++}; ++ ++static const struct prober prober_filesystem[] = { ++ { volume_id_probe_vfat, { "vfat", } }, ++ { volume_id_probe_luks, { "luks", } }, ++ { volume_id_probe_xfs, { "xfs", } }, ++ { volume_id_probe_ext, { "ext2", "ext3", "jbd", } }, ++ { volume_id_probe_reiserfs, { "reiserfs", "reiser4", } }, ++ { volume_id_probe_jfs, { "jfs", } }, ++ { volume_id_probe_hfs_hfsplus, { "hfs", "hfsplus", } }, ++ { volume_id_probe_ntfs, { "ntfs", } }, ++ { volume_id_probe_ocfs1, { "ocfs1", } }, ++ { volume_id_probe_ocfs2, { "ocfs2", } }, ++ ++ /* { volume_id_probe_linux_swap, { "swap", } }, */ ++ /* { volume_id_probe_udf, { "udf", } }, */ ++ /* { volume_id_probe_iso9660, { "iso9660", } }, */ ++ /* { volume_id_probe_ufs, { "ufs", } }, */ ++ /* { volume_id_probe_cramfs, { "cramfs", } }, */ ++ /* { volume_id_probe_romfs, { "romfs", } }, */ ++ /* { volume_id_probe_hpfs, { "hpfs", } }, */ ++ /* { volume_id_probe_sysv, { "sysv", "xenix", } }, */ ++ /* { volume_id_probe_minix, { "minix", } }, */ ++ /* { volume_id_probe_vxfs, { "vxfs", } }, */ ++ /* { volume_id_probe_squashfs, { "squashfs", } }, */ ++ /* { volume_id_probe_netware, { "netware", } }, */ ++}; ++ ++/* the user can overwrite this log function */ ++static void default_log(int priority, const char *file, int line, const char *format, ...) ++{ ++ return; ++} ++ ++volume_id_log_fn_t volume_id_log_fn = default_log; ++ ++/** ++ * volume_id_get_type: ++ * @id: Probing context ++ * @type: Type string. Must not be freed by the caller. ++ * ++ * Get the type string after a successful probe. ++ * ++ * Returns: 1 if the value was set, 0 otherwise. ++ **/ ++int volume_id_get_type(struct volume_id *id, const char **type) ++{ ++ if (id == NULL) ++ return 0; ++ if (type == NULL) ++ return 0; ++ if (id->usage_id == VOLUME_ID_UNUSED) ++ return 0; ++ ++ *type = id->type; ++ return 1; ++} ++ ++ ++/** ++ * volume_id_get_uuid: ++ * @id: Probing context. ++ * @uuid: UUID string. Must not be freed by the caller. ++ * ++ * Get the raw UUID string after a successful probe. ++ * ++ * Returns: 1 if the value was set, 0 otherwise. ++ **/ ++int volume_id_get_uuid(struct volume_id *id, const char **uuid) ++{ ++ if (id == NULL) ++ return 0; ++ if (uuid == NULL) ++ return 0; ++ if (id->usage_id == VOLUME_ID_UNUSED) ++ return 0; ++ ++ *uuid = id->uuid; ++ return 1; ++} ++ ++/** ++ * volume_id_probe_raid: ++ * @id: Probing context. ++ * @off: Probing offset relative to the start of the device. ++ * @size: Total size of the device. ++ * ++ * Probe device for all known raid signatures. ++ * ++ * Returns: 0 on successful probe, otherwise negative value. ++ **/ ++int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ unsigned int i; ++ ++ if (id == NULL) ++ return -1; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ for (i = 0; i < ARRAY_SIZE(prober_raid); i++) ++ if (prober_raid[i].prober(id, off, size) == 0) ++ goto found; ++ return -1; ++ ++found: ++ return 0; ++} ++ ++/** ++ * volume_id_probe_filesystem: ++ * @id: Probing context. ++ * @off: Probing offset relative to the start of the device. ++ * @size: Total size of the device. ++ * ++ * Probe device for all known filesystem signatures. ++ * ++ * Returns: 0 on successful probe, otherwise negative value. ++ **/ ++int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ unsigned int i; ++ ++ if (id == NULL) ++ return -1; ++ ++ info("probing at offset 0x%llx, size 0x%llx", ++ (unsigned long long) off, (unsigned long long) size); ++ ++ for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) ++ if (prober_filesystem[i].prober(id, off, size) == 0) ++ goto found; ++ return -1; ++ ++found: ++ return 0; ++} ++ ++/** ++ * volume_id_probe_raid: ++ * @all_probers_fn: prober function to called for all known probing routines. ++ * @id: Context passed to prober function. ++ * @off: Offset value passed to prober function. ++ * @size: Size value passed to prober function. ++ * @data: Arbitrary data passed to the prober function. ++ * ++ * Run a custom function for all known probing routines. ++ **/ ++void volume_id_all_probers(all_probers_fn_t all_probers_fn, ++ struct volume_id *id, uint64_t off, uint64_t size, ++ void *data) ++{ ++ unsigned int i; ++ ++ if (all_probers_fn == NULL) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(prober_raid); i++) { ++ if (all_probers_fn(prober_raid[i].prober, id, off, size, data) != 0) ++ goto out; ++ } ++ for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) { ++ if (all_probers_fn(prober_filesystem[i].prober, id, off, size, data) != 0) ++ goto out; ++ } ++out: ++ return; ++} + +=== added file 'libvolume_id/volume_id.h' +--- grub-0.97.orig/libvolume_id/volume_id.h 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/volume_id.h 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,137 @@ ++/* ++ * volume_id - reads volume label and uuid ++ * ++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _LIBVOLUME_ID_H_ ++#define _LIBVOLUME_ID_H_ ++ ++#include <stdint.h> ++#include <stddef.h> ++ ++typedef void (*volume_id_log_fn_t)(int priority, const char *file, int line, const char *format, ...) ; ++ ++extern volume_id_log_fn_t volume_id_log_fn; ++ ++struct volume_id; ++typedef int (*volume_id_probe_fn_t)(struct volume_id *id, uint64_t off, uint64_t size); ++typedef int (*all_probers_fn_t)(volume_id_probe_fn_t probe_fn, ++ struct volume_id *id, uint64_t off, uint64_t size, ++ void *data); ++ ++extern struct volume_id *volume_id_open_fd(int fd); ++extern void volume_id_close(struct volume_id *id); ++extern int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size); ++extern const volume_id_probe_fn_t *volume_id_get_prober_by_type(const char *type); ++extern void volume_id_all_probers(all_probers_fn_t all_probers_fn, ++ struct volume_id *id, uint64_t off, uint64_t size, ++ void *data); ++extern int volume_id_get_label(struct volume_id *id, const char **label); ++extern int volume_id_get_label_raw(struct volume_id *id, const uint8_t **label, size_t *len); ++extern int volume_id_get_uuid(struct volume_id *id, const char **uuid); ++extern int volume_id_get_uuid_raw(struct volume_id *id, const uint8_t **uuid, size_t *len); ++extern int volume_id_get_usage(struct volume_id *id, const char **usage); ++extern int volume_id_get_type(struct volume_id *id, const char **type); ++extern int volume_id_get_type_version(struct volume_id *id, const char **type_version); ++extern int volume_id_encode_string(const char *str, char *str_enc, size_t len); ++ ++/* ++ * Note: everything below will be made private or removed from ++ * a future version, and a new major release of libvolume_id ++ */ ++ ++extern struct volume_id *volume_id_open_node(const char *path); ++ ++#define VOLUME_ID_LABEL_SIZE 64 ++#define VOLUME_ID_UUID_SIZE 36 ++#define VOLUME_ID_FORMAT_SIZE 32 ++#define VOLUME_ID_PATH_MAX 256 ++#define VOLUME_ID_PARTITIONS_MAX 256 ++ ++enum volume_id_usage { ++ VOLUME_ID_UNUSED, ++ VOLUME_ID_UNPROBED, ++ VOLUME_ID_OTHER, ++ VOLUME_ID_FILESYSTEM, ++ VOLUME_ID_RAID, ++ VOLUME_ID_DISKLABEL, ++ VOLUME_ID_CRYPTO, ++}; ++ ++#include <util.h> ++ ++struct volume_id { ++ uint8_t label_raw[VOLUME_ID_LABEL_SIZE]; ++ size_t label_raw_len; ++ char label[VOLUME_ID_LABEL_SIZE+1]; ++ uint8_t uuid_raw[VOLUME_ID_UUID_SIZE]; ++ size_t uuid_raw_len; ++ char uuid[VOLUME_ID_UUID_SIZE+1]; ++ enum volume_id_usage usage_id; ++ char *usage; ++ char *type; ++ char type_version[VOLUME_ID_FORMAT_SIZE]; ++ ++ int fd; ++ uint8_t sbbuf[SB_BUFFER_SIZE]; ++ size_t sbbuf_len; ++ uint8_t seekbuf[SEEK_BUFFER_SIZE]; ++ uint64_t seekbuf_off; ++ size_t seekbuf_len; ++ int fd_close:1; ++}; ++ ++/* filesystems */ ++extern int volume_id_probe_cramfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ext(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_vfat(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_iso9660(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_jfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ntfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_romfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_sysv(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_udf(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ufs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_vxfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_xfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_squashfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_netware(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_gfs(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_gfs2(struct volume_id *id, uint64_t off, uint64_t size); ++ ++/* special formats */ ++extern int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_luks(struct volume_id *id, uint64_t off, uint64_t size); ++ ++/* raid */ ++extern int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_lvm1(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_lvm2(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_ddf_raid(struct volume_id *id, uint64_t off, uint64_t size); ++ ++/* bios raid */ ++extern int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_adaptec_raid(struct volume_id *id, uint64_t off, uint64_t size); ++extern int volume_id_probe_jmicron_raid(struct volume_id *id, uint64_t off, uint64_t size); ++ ++#endif + +=== added file 'libvolume_id/vxfs.c' +--- grub-0.97.orig/libvolume_id/vxfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/vxfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,49 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++#define VXFS_SUPER_MAGIC 0xa501FCF5 ++ ++struct vxfs_super { ++ uint32_t vs_magic; ++ int32_t vs_version; ++} PACKED; ++ ++int volume_id_probe_vxfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct vxfs_super *vxs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ vxs = (struct vxfs_super *) volume_id_get_buffer(id, off + 0x200, 0x200); ++ if (vxs == NULL) ++ return -1; ++ ++ if (vxs->vs_magic == cpu_to_le32(VXFS_SUPER_MAGIC)) { ++ sprintf(id->type_version, "%u", (unsigned int) vxs->vs_version); ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "vxfs"; ++ return 0; ++ } ++ ++ return -1; ++} + +=== added file 'libvolume_id/xfs.c' +--- grub-0.97.orig/libvolume_id/xfs.c 1970-01-01 00:00:00 +0000 ++++ grub-0.97/libvolume_id/xfs.c 2008-07-15 12:31:43 +0000 +@@ -0,0 +1,59 @@ ++/* ++ * volume_id - reads filesystem label and uuid ++ * ++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation version 2 of the License. ++ */ ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#ifdef HAVE_CONFIG_H ++# include <config.h> ++#endif ++ ++#include "volume_id.h" ++#include "util.h" ++#include "shared.h" ++ ++struct xfs_super_block { ++ uint8_t magic[4]; ++ uint32_t blocksize; ++ uint64_t dblocks; ++ uint64_t rblocks; ++ uint32_t dummy1[2]; ++ uint8_t uuid[16]; ++ uint32_t dummy2[15]; ++ uint8_t fname[12]; ++ uint32_t dummy3[2]; ++ uint64_t icount; ++ uint64_t ifree; ++ uint64_t fdblocks; ++} PACKED; ++ ++int volume_id_probe_xfs(struct volume_id *id, uint64_t off, uint64_t size) ++{ ++ struct xfs_super_block *xs; ++ ++ info("probing at offset 0x%llx", (unsigned long long) off); ++ ++ xs = (struct xfs_super_block *) volume_id_get_buffer(id, off, 0x200); ++ if (xs == NULL) ++ return -1; ++ ++ if (memcmp((char *)xs->magic, "XFSB", 4) != 0) ++ return -1; ++ ++ volume_id_set_label_raw(id, xs->fname, 12); ++ volume_id_set_label_string(id, xs->fname, 12); ++ volume_id_set_uuid(id, xs->uuid, 0, UUID_DCE); ++ ++ volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); ++ id->type = "xfs"; ++ ++ return 0; ++} + +=== modified file 'stage2/Makefile.am' +--- grub-0.97.orig/stage2/Makefile.am 2005-02-02 20:40:05 +0000 ++++ grub-0.97/stage2/Makefile.am 2008-07-09 17:23:44 +0000 +@@ -13,6 +13,10 @@ + # For <stage1.h>. + INCLUDES = -I$(top_srcdir)/stage1 + ++if UUID_SUPPORT ++INCLUDES += -I$(top_srcdir)/libvolume_id ++endif ++ + # The library for /sbin/grub. + noinst_LIBRARIES = libgrub.a + libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \ +@@ -61,6 +65,12 @@ + PXELOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00 + START_ELTORITO_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00 + ++if UUID_SUPPORT ++UUID_FLAGS = -DSUPPORT_UUID=1 ++else ++UUID_FLAGS = ++endif ++ + if NETBOOT_SUPPORT + NETBOOT_FLAGS = -I$(top_srcdir)/netboot -DSUPPORT_NETBOOT=1 + else +@@ -82,6 +92,8 @@ + STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ + $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) + ++STAGE2_COMPILE += $(UUID_FLAGS) ++ + STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000 + STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 + +@@ -97,7 +109,12 @@ + + if NETBOOT_SUPPORT + pre_stage2_exec_LDADD = ../netboot/libdrivers.a +-endif ++else ++if UUID_SUPPORT ++pre_stage2_exec_LDADD = ../libvolume_id/libvolume_id.a ++endif ++endif ++ + + if DISKLESS_SUPPORT + BUILT_SOURCES = stage2_size.h diskless_size.h + +=== modified file 'stage2/builtins.c' +--- grub-0.97.orig/stage2/builtins.c 2008-01-28 18:15:31 +0000 ++++ grub-0.97/stage2/builtins.c 2008-07-09 17:23:44 +0000 +@@ -49,6 +49,10 @@ + # include <md5.h> + #endif + ++#ifdef SUPPORT_UUID ++#include <volume_id.h> ++#endif ++ + /* The type of kernel loaded. */ + kernel_t kernel_type; + /* The boot device. */ +@@ -4790,6 +4794,168 @@ + "Probe VBE information. If the mode number MODE is specified, show only" + " the information about only the mode." + }; ++ ++ ++ ++#ifdef SUPPORT_UUID ++ ++struct uuid_callback_data ++{ ++ int found; /* 1 if uuid matches */ ++ char *uuid; /* uuid to look for */ ++}; ++ ++static void uuid_info_print(struct volume_id *id, const char *uuid) ++{ ++ const char *type; ++ int i; ++ ++ volume_id_get_type(id, &type); ++ grub_printf("(hd%d", current_drive - 0x80); ++ if ((current_partition & 0xFF0000) != 0xFF0000) ++ { ++ grub_printf (",%d", (current_partition >> 16) & 0xFF); ++ } ++ if ((current_partition & 0x00FF00) != 0x00FF00) ++ { ++ grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF)); ++ } ++ grub_printf(") %s",type); ++ for (i=0;i<6-strlen(type);i++) ++ { ++ grub_putchar(' '); ++ } ++ grub_printf(" %s\n",uuid); ++} ++ ++static int uuid_all_probers(volume_id_probe_fn_t probe_fn, ++ struct volume_id *id, ++ uint64_t off, ++ uint64_t size, ++ void *data) ++{ ++ struct uuid_callback_data *uc_data = (struct uuid_callback_data*)data; ++ ++ if (probe_fn(id, off, size) == 0) ++ { ++ const char *volume_uuid; ++ if (volume_id_get_uuid(id, &volume_uuid)) ++ { ++ if (!*(uc_data->uuid)) ++ { ++ uuid_info_print(id, volume_uuid); ++ } ++ else ++ { ++ if (strcmp(volume_uuid, uc_data->uuid) == 0) ++ { ++ grub_printf("Boot from "); ++ uuid_info_print(id, volume_uuid); ++ uc_data->found = 1; ++ return 1; ++ } ++ } ++ } ++ } ++ return 0; ++} ++ ++/* uuid find */ ++/* Search for the uuid arg in all of partitions. */ ++static int ++uuid_func(char *arg, int flag) ++{ ++ unsigned long drive; ++ unsigned long tmp_drive = saved_drive; ++ unsigned long tmp_partition = saved_partition; ++ struct uuid_callback_data uc_data; ++ ++ uc_data.uuid = arg; ++ uc_data.found = 0; ++ ++ /* Just hard disks and USB drives supported by BIOS */ ++ for (drive = 0x80; drive < 0x88; drive++) ++ { ++ unsigned long part = 0xFFFFFF; ++ unsigned long start, len, offset, ext_offset, gpt_offset; ++ int type, entry, gpt_count, gpt_size; ++ char *buf = (char *) RAW_ADDR(0x100000); ++ struct volume_id *vol_id = (struct volume_id *) RAW_ADDR (0x100000 + SECTOR_SIZE); ++ ++ current_drive = drive; ++ while (next_partition (drive, 0xFFFFFF, &part, &type, ++ &start, &len, &offset, &entry, ++ &ext_offset, &gpt_offset, ++ &gpt_count, &gpt_size, buf)) ++ { ++ if (type != PC_SLICE_TYPE_NONE ++ && ! IS_PC_SLICE_TYPE_BSD (type) ++ && ! IS_PC_SLICE_TYPE_EXTENDED (type)) ++ { ++ current_partition = part; ++ errnum = ERR_NONE; ++ /* Attempt to open device, conventional way */ ++ if (! open_device ()) ++ { ++ errnum = ERR_NONE; ++ /* Failed, like NTFS or FAT filesystems, so try the rootnoverify way */ ++ if (open_partition ()) ++ { ++ set_bootdev (0); ++ if (errnum) ++ { ++ /* Give up */ ++ errnum = ERR_NONE; ++ continue; ++ } ++ } ++ } ++ ++ /* And probe for uuid across all fs types */ ++ saved_drive = current_drive; ++ saved_partition = current_partition; ++ ++ grub_memset(vol_id, 0, sizeof(struct volume_id) ); ++ volume_id_all_probers(uuid_all_probers, vol_id, 0, len, (void*)&uc_data); ++ if (uc_data.found) ++ { ++ /* Success! */ ++ errnum = ERR_NONE; ++ return 0; ++ } ++ } ++ /* We want to ignore any error here. */ ++ errnum = ERR_NONE; ++ } ++ ++ /* next_partition always sets ERRNUM in the last call, so clear it. */ ++ errnum = ERR_NONE; ++ } ++ ++ saved_drive = tmp_drive; ++ saved_partition = tmp_partition; ++ current_drive = GRUB_INVALID_DRIVE; ++ current_partition = 0xFFFFFF; ++ errnum = ERR_FILE_NOT_FOUND; ++ ++ if (!*arg) ++ { ++ errnum = ERR_NONE; ++ return 0; ++ } ++ return 1; ++} ++ ++static struct builtin builtin_uuid = ++{ ++ "uuid", ++ uuid_func, ++ BUILTIN_CMDLINE | BUILTIN_HELP_LIST, ++ "uuid UUID", ++ "Set the current \"root device\" to the device with the uuid UUID," ++ " then attempt to mount it" ++}; ++#endif + + + /* The table of builtin commands. Sorted in dictionary order. */ +@@ -4879,6 +5045,9 @@ + &builtin_title, + &builtin_unhide, + &builtin_uppermem, ++#ifdef SUPPORT_UUID ++ &builtin_uuid, ++#endif + &builtin_vbeprobe, + 0 + }; + diff --git a/sys-boot/grub/files/grub-0.97-uuid_doc.patch b/sys-boot/grub/files/grub-0.97-uuid_doc.patch new file mode 100644 index 00000000..06bfbdeb --- /dev/null +++ b/sys-boot/grub/files/grub-0.97-uuid_doc.patch @@ -0,0 +1,38 @@ +--- grub-0.97.orig/docs/grub.texi 2008-07-17 11:07:25.000000000 +0100 ++++ grub-0.97/docs/grub.texi 2008-07-17 10:57:41.000000000 +0100 +@@ -2707,6 +2707,7 @@ + * testload:: Load a file for testing a filesystem + * testvbe:: Test VESA BIOS EXTENSION + * uppermem:: Set the upper memory size ++* uuid:: Set GRUB's root device using UUID + * vbeprobe:: Probe VESA BIOS EXTENSION + @end menu + +@@ -3266,6 +3267,27 @@ + also be used for debugging purposes to lie to an OS. + @end deffn + ++@node uuid ++@subsection uuid ++ ++@deffn Command uuid [UUID] ++Set the current @dfn{root device} to the device with the universally ++unique identifier @var{UUID}, then attempt to mount it. This is ++equivalent to the @ref{root} command, but allows one to select a ++filesystem by UUID rather than by device. ++ ++The command recognises ext2, ext3, fat, hfs, jfs, ntfs, ocfs, reiserfs ++and xfs filesystems. ++ ++@strong{Note:} grub detects and recognises fat UUIDs in lower case ++whereas examining /dev/disk/by-uuid on Linux will report fat UUIDs ++in upper case. ++ ++By not specifying @var{UUID}, the command will scan partitions on ++attached devices and will display the device, partition type and ++UUID for each recognised filesystem. ++@end deffn ++ + + @node vbeprobe + @subsection vbeprobe diff --git a/sys-boot/grub/files/grub-1.96-genkernel.patch b/sys-boot/grub/files/grub-1.96-genkernel.patch new file mode 100644 index 00000000..e06f3835 --- /dev/null +++ b/sys-boot/grub/files/grub-1.96-genkernel.patch @@ -0,0 +1,19 @@ +--- util/grub.d/10_linux.in ++++ util/grub.d/10_linux.in +@@ -61,7 +61,7 @@ + EOF + } + +-list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do ++list=`for i in /boot/kernel-* /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do + if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi + done` + +@@ -78,6 +78,7 @@ + initrd= + for i in "initrd.img-${version}" "initrd-${version}.img" \ + "initrd-${version}" "initrd.img-${alt_version}" \ ++ "initramfs-genkernel-${version}" "initramfs-genkernel-${alt_version}" \ + "initrd-${alt_version}.img" "initrd-${alt_version}"; do + if test -e "${dirname}/${i}" ; then + initrd="$i" diff --git a/sys-boot/grub/files/grub-1.97-genkernel.patch b/sys-boot/grub/files/grub-1.97-genkernel.patch new file mode 100644 index 00000000..ae64ae45 --- /dev/null +++ b/sys-boot/grub/files/grub-1.97-genkernel.patch @@ -0,0 +1,28 @@ +--- grub-1.97.2.orig/util/grub.d/10_linux.in ++++ grub-1.97.2/util/grub.d/10_linux.in +@@ -49,7 +49,7 @@ menuentry "$1" { + EOF + prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" + cat << EOF +- linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro $2 ++ linux ${rel_dirname}/${basename} ro $2 + EOF + if test -n "${initrd}" ; then + cat << EOF +@@ -61,7 +61,7 @@ EOF + EOF + } + +-list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do ++list=`for i in /boot/kernel-* /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do + if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi + done` + +@@ -78,6 +78,7 @@ while [ "x$list" != "x" ] ; do + initrd= + for i in "initrd.img-${version}" "initrd-${version}.img" \ + "initrd-${version}" "initrd.img-${alt_version}" \ ++ "initramfs-genkernel-${version}" "initramfs-genkernel-${alt_version}" \ + "initrd-${alt_version}.img" "initrd-${alt_version}"; do + if test -e "${dirname}/${i}" ; then + initrd="$i" diff --git a/sys-boot/grub/files/grub-1.97-hostdisk.patch b/sys-boot/grub/files/grub-1.97-hostdisk.patch new file mode 100644 index 00000000..6eb7fe48 --- /dev/null +++ b/sys-boot/grub/files/grub-1.97-hostdisk.patch @@ -0,0 +1,60 @@ +--- util/hostdisk.c 2010-01-25 17:04:22 +0000 ++++ util/hostdisk.c 2010-01-31 11:52:27 +0000 +@@ -336,7 +336,8 @@ + char dev[PATH_MAX]; + + strcpy (dev, map[disk->id].device); +- if (disk->partition && strncmp (map[disk->id].device, "/dev/", 5) == 0) ++ if (disk->partition && sector >= disk->partition->start ++ && strncmp (map[disk->id].device, "/dev/", 5) == 0) + is_partition = linux_find_partition (dev, disk->partition->start); + + /* Open the partition. */ +@@ -490,6 +491,23 @@ + { + int fd; + ++ /* Split pre-partition and partition reads. */ ++ if (disk->partition && sector < disk->partition->start ++ && sector + size > disk->partition->start) ++ { ++ grub_err_t err; ++ err = grub_util_biosdisk_read (disk, sector, ++ disk->partition->start - sector, ++ buf); ++ if (err) ++ return err; ++ ++ return grub_util_biosdisk_read (disk, disk->partition->start, ++ size - (disk->partition->start - sector), ++ buf + ((disk->partition->start - sector) ++ << GRUB_DISK_SECTOR_BITS)); ++ } ++ + fd = open_device (disk, sector, O_RDONLY); + if (fd < 0) + return grub_errno; +@@ -527,6 +545,23 @@ + { + int fd; + ++ /* Split pre-partition and partition writes. */ ++ if (disk->partition && sector < disk->partition->start ++ && sector + size > disk->partition->start) ++ { ++ grub_err_t err; ++ err = grub_util_biosdisk_write (disk, sector, ++ disk->partition->start - sector, ++ buf); ++ if (err) ++ return err; ++ ++ return grub_util_biosdisk_write (disk, disk->partition->start, ++ size - (disk->partition->start - sector), ++ buf + ((disk->partition->start - sector) ++ << GRUB_DISK_SECTOR_BITS)); ++ } ++ + fd = open_device (disk, sector, O_WRONLY); + if (fd < 0) + return grub_errno; diff --git a/sys-boot/grub/files/grub-1.97-vga-deprecated.patch b/sys-boot/grub/files/grub-1.97-vga-deprecated.patch new file mode 100644 index 00000000..16b2ef7e --- /dev/null +++ b/sys-boot/grub/files/grub-1.97-vga-deprecated.patch @@ -0,0 +1,12 @@ +--- grub-1.97.2.orig/util/grub.d/00_header.in ++++ grub-1.97.2/util/grub.d/00_header.in +@@ -76,6 +76,9 @@ case x${GRUB_TERMINAL_OUTPUT} in + cat << EOF + if loadfont `make_system_path_relative_to_its_root ${GRUB_FONT_PATH}` ; then + set gfxmode=${GRUB_GFXMODE} ++ # vga= is deprecated, grub2 handles this just fine ++ # making grub2 res == linux fb res ++ set gfxpayload=keep + insmod gfxterm + insmod ${GRUB_VIDEO_BACKEND} + if terminal_output gfxterm ; then true ; else diff --git a/sys-boot/grub/files/grub-1.97-wallpaper-settings-support.patch b/sys-boot/grub/files/grub-1.97-wallpaper-settings-support.patch new file mode 100644 index 00000000..3bf4ffa8 --- /dev/null +++ b/sys-boot/grub/files/grub-1.97-wallpaper-settings-support.patch @@ -0,0 +1,15 @@ +diff -Nurp grub-1.97.2.orig/util/grub-mkconfig.in grub-1.97.2/util/grub-mkconfig.in +--- grub-1.97.2.orig/util/grub-mkconfig.in 2010-01-24 19:13:30.000000000 +0100 ++++ grub-1.97.2/util/grub-mkconfig.in 2010-02-17 21:01:08.762963506 +0100 +@@ -224,7 +224,10 @@ export GRUB_DEFAULT \ + GRUB_DISABLE_LINUX_UUID \ + GRUB_DISABLE_LINUX_RECOVERY \ + GRUB_GFXMODE \ +- GRUB_DISABLE_OS_PROBER ++ GRUB_DISABLE_OS_PROBER \ ++ GRUB_WALLPAPER \ ++ GRUB_COLOR_NORMAL \ ++ GRUB_COLOR_HIGHLIGHT + + if test "x${grub_cfg}" != "x"; then + rm -f ${grub_cfg}.new diff --git a/sys-boot/grub/files/grub-1.98-add-legacy-rootfs-detection.patch b/sys-boot/grub/files/grub-1.98-add-legacy-rootfs-detection.patch new file mode 100644 index 00000000..1fadd461 --- /dev/null +++ b/sys-boot/grub/files/grub-1.98-add-legacy-rootfs-detection.patch @@ -0,0 +1,83 @@ +diff -ur grub2-orig/util/grub-mkconfig.in grub2-new/util/grub-mkconfig.in +--- grub2-orig/util/grub-mkconfig.in 2010-01-28 15:01:46.746567396 +0100 ++++ grub2-new/util/grub-mkconfig.in 2010-01-28 15:38:48.560587115 +0100 +@@ -119,8 +119,8 @@ + fi + + # Device containing our userland. Typically used for root= parameter. +-GRUB_DEVICE="`${grub_probe} --target=device /`" +-GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true ++GRUB_DEVICE="`${grub_probe} --target=device /`" || GRUB_DEVICE="`legacy_find_root_device`" ++GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || GRUB_DEVICE_UUID="`legacy_convert_to_uuid ${GRUB_DEVICE}`" + + # Device containing our /boot partition. Usually the same as GRUB_DEVICE. + GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`" +diff -ur grub2-orig/util/grub-mkconfig_lib.in grub2-new/util/grub-mkconfig_lib.in +--- grub2-orig/util/grub-mkconfig_lib.in 2010-01-28 15:01:46.740383831 +0100 ++++ grub2-new/util/grub-mkconfig_lib.in 2010-01-28 15:38:10.474013430 +0100 +@@ -188,3 +188,65 @@ + done + echo "$a" + } ++ ++legacy_find_root_device () ++{ ++ mount_point=$1 ++ ++ # Autodetect current root device ++ device= ++ if [ -f /etc/fstab ] ; then ++ device="`awk '$1!~/^#/{ ++ if ($2 ~ "^/+$") { $2 = "/"; } else { sub("/*$", "", $2); } ++ if ($2 == "'"$mount_point"'"){ ++ print $1; ++ } ++ }' /etc/fstab | tail -n 1`" ++ fi ++ ++ if [ -n "$device" ] ; then ++ case "$device" in ++ LABEL=* | UUID=*) ++ device="`findfs $device`" ++ device="`readlink -f "$device"`" ++ ;; ++ *) ++ device=`readlink -f "$device"` ++ ;; ++ esac ++ fi ++ ++ echo $device ++} ++ ++legacy_convert_to_uuid() ++{ ++ echo "Cannot determine uuid of root device. Trying legacy probe method" >&2 ++ local dev; dev="$1" ++ ++ convert=false ++ case "$dev" in ++ /dev/disk/*) ++ ;; ++ /dev/mapper/*) ++ ;; ++ /dev/evms/[hs]d[a-z][0-9]*) ++ convert=: ++ ;; ++ /dev/evms/*) ++ ;; ++ /dev/md[0-9]*) ++ ;; ++ /dev/*) ++ convert=: ++ ;; ++ esac ++ if $convert; then ++ if [ -b "$dev" ]; then ++ uuid="`blkid -o value -s UUID "$dev" || true`" ++ fi ++ fi ++ ++ echo "$uuid" ++} ++ diff --git a/sys-boot/grub/files/grub-1.98-follow-dev-mapper-symlinks.patch b/sys-boot/grub/files/grub-1.98-follow-dev-mapper-symlinks.patch new file mode 100644 index 00000000..aead475c --- /dev/null +++ b/sys-boot/grub/files/grub-1.98-follow-dev-mapper-symlinks.patch @@ -0,0 +1,25 @@ +--- a/util/getroot.c 2010-03-06 20:51:37.000000000 +0000 ++++ b/util/getroot.c 2010-05-28 19:21:57.592307313 +0100 +@@ -222,9 +222,20 @@ find_root_device (const char *dir, dev_t + /* Ignore any error. */ + continue; + +- if (S_ISLNK (st.st_mode)) +- /* Don't follow symbolic links. */ ++ if (S_ISLNK (st.st_mode)) { ++#ifdef __linux__ ++ if (strcmp (dir, "mapper") == 0) { ++ /* Follow symbolic links under /dev/mapper/; the canonical name ++ may be something like /dev/dm-0, but the names under ++ /dev/mapper/ are more human-readable and so we prefer them if ++ we can get them. */ ++ if (stat (ent->d_name, &st) < 0) ++ continue; ++ } else ++#endif /* __linux__ */ ++ /* Don't follow other symbolic links. */ + continue; ++ } + + if (S_ISDIR (st.st_mode)) + { diff --git a/sys-boot/grub/files/grub-1.98-genkernel-initramfs-single.patch b/sys-boot/grub/files/grub-1.98-genkernel-initramfs-single.patch new file mode 100644 index 00000000..4aa6ab99 --- /dev/null +++ b/sys-boot/grub/files/grub-1.98-genkernel-initramfs-single.patch @@ -0,0 +1,11 @@ +--- grub-1.99.orig/util/grub.d/10_linux.in ++++ grub-1.99/util/grub.d/10_linux.in +@@ -192,7 +192,7 @@ while [ "x$list" != "x" ] ; do + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then + linux_entry "${OS}" "${version}" true \ +- "single ${GRUB_CMDLINE_LINUX}" ++ "single init_opts=single ${GRUB_CMDLINE_LINUX/splash=silent/splash=verbose}" + fi + + list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '` diff --git a/sys-boot/grub/files/grub-1.98-genkernel.patch b/sys-boot/grub/files/grub-1.98-genkernel.patch new file mode 100644 index 00000000..8fbf39ab --- /dev/null +++ b/sys-boot/grub/files/grub-1.98-genkernel.patch @@ -0,0 +1,28 @@ +--- grub-1.98.orig/util/grub.d/10_linux.in 2010-03-06 21:51:37.000000000 +0100 ++++ grub-1.98/util/grub.d/10_linux.in 2010-04-12 11:25:51.982167950 +0200 +@@ -84,7 +84,7 @@ EOF + printf '%s\n' "${prepare_boot_cache}" + cat << EOF + echo $(printf "$(gettext "Loading Linux %s ...")" ${version}) +- linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} ++ linux ${rel_dirname}/${basename} ro ${args} + EOF + if test -n "${initrd}" ; then + cat << EOF +@@ -97,7 +97,7 @@ EOF + EOF + } + +-list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do ++list=`for i in /boot/kernel-* /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do + if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi + done` + prepare_boot_cache= +@@ -114,6 +114,7 @@ while [ "x$list" != "x" ] ; do + + initrd= + for i in "initrd.img-${version}" "initrd-${version}.img" \ ++ "initramfs-genkernel-${version}" "initramfs-genkernel-${alt_version}" \ + "initrd-${version}" "initrd.img-${alt_version}" \ + "initrd-${alt_version}.img" "initrd-${alt_version}"; do + if test -e "${dirname}/${i}" ; then diff --git a/sys-boot/grub/files/grub-1.98-wallpaper-settings-support.patch b/sys-boot/grub/files/grub-1.98-wallpaper-settings-support.patch new file mode 100644 index 00000000..f34f393b --- /dev/null +++ b/sys-boot/grub/files/grub-1.98-wallpaper-settings-support.patch @@ -0,0 +1,15 @@ +diff -Nurp grub-1.98.orig/util/grub-mkconfig.in grub-1.98/util/grub-mkconfig.in +--- grub-1.98.orig/util/grub-mkconfig.in 2010-03-06 21:51:37.000000000 +0100 ++++ grub-1.98/util/grub-mkconfig.in 2010-04-12 11:29:28.396075050 +0200 +@@ -224,7 +224,10 @@ export GRUB_DEFAULT \ + GRUB_GFXPAYLOAD_LINUX \ + GRUB_DISABLE_OS_PROBER \ + GRUB_INIT_TUNE \ +- GRUB_SAVEDEFAULT ++ GRUB_SAVEDEFAULT \ ++ GRUB_WALLPAPER \ ++ GRUB_COLOR_NORMAL \ ++ GRUB_COLOR_HIGHLIGHT + + if test "x${grub_cfg}" != "x"; then + rm -f ${grub_cfg}.new diff --git a/sys-boot/grub/files/grub-1.99-disable-floppies.patch b/sys-boot/grub/files/grub-1.99-disable-floppies.patch new file mode 100644 index 00000000..6bb28626 --- /dev/null +++ b/sys-boot/grub/files/grub-1.99-disable-floppies.patch @@ -0,0 +1,28 @@ + +Author: Robert Millan + +An ugly kludge. Should this be merged upstream? + +Index: b/grub-core/kern/emu/hostdisk.c +=================================================================== +--- a/grub-core/kern/emu/hostdisk.c ++++ b/grub-core/kern/emu/hostdisk.c +@@ -1077,6 +1077,18 @@ + continue; + } + ++ if (! strncmp (p, "/dev/fd", sizeof ("/dev/fd") - 1)) ++ { ++ char *q = p + sizeof ("/dev/fd") - 1; ++ if (*q >= '0' && *q <= '9') ++ { ++ free (map[drive].drive); ++ map[drive].drive = NULL; ++ grub_util_info ("`%s' looks like a floppy drive, skipping", p); ++ continue; ++ } ++ } ++ + #ifdef __linux__ + /* On Linux, the devfs uses symbolic links horribly, and that + confuses the interface very much, so use realpath to expand diff --git a/sys-boot/grub/files/grub-1.99-genkernel.patch b/sys-boot/grub/files/grub-1.99-genkernel.patch new file mode 100644 index 00000000..433e583d --- /dev/null +++ b/sys-boot/grub/files/grub-1.99-genkernel.patch @@ -0,0 +1,11 @@ +--- grub-1.99.orig/util/grub.d/10_linux.in ++++ grub-1.99/util/grub.d/10_linux.in +@@ -116,7 +116,7 @@ EOF + message="$(gettext_printf "Loading Linux %s ..." ${version})" + cat << EOF + echo '$message' +- linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} ++ linux ${rel_dirname}/${basename} ro ${args} + EOF + if test -n "${initrd}" ; then + message="$(gettext_printf "Loading initial ramdisk ...")" diff --git a/sys-boot/grub/files/grub-1.99-vga-deprecated-not-yet.patch b/sys-boot/grub/files/grub-1.99-vga-deprecated-not-yet.patch new file mode 100644 index 00000000..d850c178 --- /dev/null +++ b/sys-boot/grub/files/grub-1.99-vga-deprecated-not-yet.patch @@ -0,0 +1,14 @@ +diff -Nurp grub-1.99.orig/grub-core/loader/i386/linux.c grub-1.99/grub-core/loader/i386/linux.c +--- grub-1.99.orig/grub-core/loader/i386/linux.c 2011-06-11 10:49:46.975998646 +0200 ++++ grub-1.99/grub-core/loader/i386/linux.c 2011-06-11 11:52:14.419996325 +0200 +@@ -821,10 +821,6 @@ grub_cmd_linux (grub_command_t cmd __att + if (! buf) + goto fail; + +- grub_printf ("%s is deprecated. " +- "Use set gfxpayload=%s before " +- "linux command instead.\n", +- argv[i], buf); + err = grub_env_set ("gfxpayload", buf); + grub_free (buf); + if (err) diff --git a/sys-boot/grub/files/grub-1.99-vga-deprecated.patch b/sys-boot/grub/files/grub-1.99-vga-deprecated.patch new file mode 100644 index 00000000..20ea6d89 --- /dev/null +++ b/sys-boot/grub/files/grub-1.99-vga-deprecated.patch @@ -0,0 +1,12 @@ +--- grub-1.99~rc1.orig/util/grub.d/00_header.in ++++ grub-1.99~rc1/util/grub.d/00_header.in +@@ -131,6 +131,9 @@ if [ "x$gfxterm" = x1 ]; then + if loadfont `make_system_path_relative_to_its_root "${GRUB_FONT_PATH}"` ; then + set gfxmode=${GRUB_GFXMODE} + load_video ++ # vga= is deprecated, grub2 handles this just fine ++ # making grub2 res == linux fb res ++ set gfxpayload=keep + insmod gfxterm + fi + EOF diff --git a/sys-boot/grub/files/grub-1.99-wallpaper-settings-support.patch b/sys-boot/grub/files/grub-1.99-wallpaper-settings-support.patch new file mode 100644 index 00000000..6f3f3749 --- /dev/null +++ b/sys-boot/grub/files/grub-1.99-wallpaper-settings-support.patch @@ -0,0 +1,15 @@ +diff -Nurp grub-1.99~rc1.orig/util/grub-mkconfig.in grub-1.99~rc1/util/grub-mkconfig.in +--- grub-1.99~rc1.orig/util/grub-mkconfig.in 2010-12-01 15:45:43.000000000 +0100 ++++ grub-1.99~rc1/util/grub-mkconfig.in 2011-06-08 14:37:02.209761705 +0200 +@@ -254,7 +254,10 @@ export GRUB_DEFAULT \ + GRUB_DISABLE_OS_PROBER \ + GRUB_INIT_TUNE \ + GRUB_SAVEDEFAULT \ +- GRUB_BADRAM ++ GRUB_BADRAM \ ++ GRUB_WALLPAPER \ ++ GRUB_COLOR_NORMAL \ ++ GRUB_COLOR_HIGHLIGHT + + if test "x${grub_cfg}" != "x"; then + rm -f ${grub_cfg}.new diff --git a/sys-boot/grub/files/grub-1.99-workaround-raid-bios-bug.patch b/sys-boot/grub/files/grub-1.99-workaround-raid-bios-bug.patch new file mode 100644 index 00000000..391c40ac --- /dev/null +++ b/sys-boot/grub/files/grub-1.99-workaround-raid-bios-bug.patch @@ -0,0 +1,17 @@ +diff -Nurp grub-1.99.orig/grub-core/disk/raid.c grub-1.99/grub-core/disk/raid.c +--- grub-1.99.orig/grub-core/disk/raid.c 2011-04-18 23:16:16.000000000 +0200 ++++ grub-1.99/grub-core/disk/raid.c 2011-06-11 10:48:16.606998702 +0200 +@@ -562,13 +562,6 @@ insert_array (grub_disk_t disk, struct g + "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; diff --git a/sys-boot/grub/files/grub-2.00-20_linux_xen.patch b/sys-boot/grub/files/grub-2.00-20_linux_xen.patch new file mode 100644 index 00000000..c83f0b04 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-20_linux_xen.patch @@ -0,0 +1,14 @@ +Fix detection of genkernel initramfs for xen + +https://bugs.gentoo.org/show_bug.cgi?id=463992 + +--- a/util/grub.d/20_linux_xen.in ++++ b/util/grub.d/20_linux_xen.in +@@ -174,6 +174,7 @@ + + title_correction_code= + ++machine=`uname -m` + case "$machine" in + i?86) GENKERNEL_ARCH="x86" ;; + mips|mips64) GENKERNEL_ARCH="mips" ;; diff --git a/sys-boot/grub/files/grub-2.00-compression.patch b/sys-boot/grub/files/grub-2.00-compression.patch new file mode 100644 index 00000000..58bc1f93 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-compression.patch @@ -0,0 +1,84 @@ +https://bugs.gentoo.org/show_bug.cgi?id=424527 +https://savannah.gnu.org/bugs/index.php?36770 + +=== modified file 'grub-core/lib/xzembed/xz_dec_stream.c' +--- grub-core/lib/xzembed/xz_dec_stream.c 2012-02-29 13:56:51 +0000 ++++ grub-core/lib/xzembed/xz_dec_stream.c 2012-07-22 14:27:03 +0000 +@@ -403,18 +403,25 @@ + } + #endif + +- do { ++ if (b->in_pos == b->in_size) ++ return XZ_OK; ++ ++ if (!crc32 && s->hash_size == 0) ++ s->pos += 8; ++ ++ while (s->pos < (crc32 ? 32 : s->hash_size * 8)) { + if (b->in_pos == b->in_size) + return XZ_OK; + + #ifndef GRUB_EMBED_DECOMPRESSOR +- if (hash && s->hash_value[s->pos / 8] != b->in[b->in_pos++]) ++ if (hash && s->hash_value[s->pos / 8] != b->in[b->in_pos]) + return XZ_DATA_ERROR; + #endif ++ b->in_pos++; + + s->pos += 8; + +- } while (s->pos < (crc32 ? 32 : s->hash_size * 8)); ++ } + + #ifndef GRUB_EMBED_DECOMPRESSOR + if (s->hash) +@@ -529,8 +536,6 @@ + s->hash->init(s->index.hash.hash_context); + s->hash->init(s->block.hash.hash_context); + } +- if (!s->hash) +- return XZ_OPTIONS_ERROR; + #endif + } + else + +=== modified file 'grub-core/normal/autofs.c' +--- grub-core/normal/autofs.c 2012-05-01 13:26:36 +0000 ++++ grub-core/normal/autofs.c 2012-07-22 14:23:46 +0000 +@@ -32,11 +32,21 @@ + autoload_fs_module (void) + { + grub_named_list_t p; ++ int ret = 0; ++ grub_file_filter_t grub_file_filters_was[GRUB_FILE_FILTER_MAX]; ++ ++ grub_memcpy (grub_file_filters_was, grub_file_filters_enabled, ++ sizeof (grub_file_filters_enabled)); ++ grub_memcpy (grub_file_filters_enabled, grub_file_filters_all, ++ sizeof (grub_file_filters_enabled)); + + while ((p = fs_module_list) != NULL) + { + if (! grub_dl_get (p->name) && grub_dl_load (p->name)) +- return 1; ++ { ++ ret = 1; ++ break; ++ } + + if (grub_errno) + grub_print_error (); +@@ -46,7 +56,10 @@ + grub_free (p); + } + +- return 0; ++ grub_memcpy (grub_file_filters_enabled, grub_file_filters_was, ++ sizeof (grub_file_filters_enabled)); ++ ++ return ret; + } + + /* Read the file fs.lst for auto-loading. */ + diff --git a/sys-boot/grub/files/grub-2.00-config-quoting.patch b/sys-boot/grub/files/grub-2.00-config-quoting.patch new file mode 100644 index 00000000..3b031c62 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-config-quoting.patch @@ -0,0 +1,113 @@ +https://bugs.gentoo.org/show_bug.cgi?id=426364 +https://savannah.gnu.org/bugs/index.php?36839 +--- util/grub-mkconfig_lib.in ++++ util/grub-mkconfig_lib.in +@@ -255,19 +255,19 @@ + echo "$version_find_latest_a" + } + +-# One layer of quotation is eaten by "", the second by sed, and the third by +-# printf; so this turns ' into \'. Note that you must use the output of ++# One layer of quotation is eaten by "" and the second by ++# sed; so this turns ' into \'. Note that you must use the output of + # this function in a printf format string. + + grub_quote () { +- sed "s/'/'\\\\\\\\''/g" ++ sed "s/'/'\\\\''/g" + } + + gettext_quoted () { +- gettext "$@" | sed "s/'/'\\\\\\\\''/g" ++ gettext "$@" | grub_quote + } + +-# Run the first argument through gettext_quoted, and then pass that and all ++# Run the first argument through gettext, and then pass that and all + # remaining arguments to printf. This is a useful abbreviation and tends to + # be easier to type. + gettext_printf () { + +=== modified file 'util/grub.d/10_hurd.in' +--- util/grub.d/10_hurd.in ++++ util/grub.d/10_hurd.in +@@ -117,7 +117,7 @@ + opts= + fi + sed "s/^/$submenu_indentation/" << EOF +- echo '$message' ++ echo '$(echo "$message" | grub_quote)' + multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} $opts ${GRUB_CMDLINE_GNUMACH} + EOF + +@@ -133,7 +133,7 @@ + fi + + sed "s/^/$submenu_indentation/" << EOF +- echo '$message' ++ echo '$(echo "$message" | grub_quote)' + module /hurd/${hurd_fs}.static ${hurd_fs} $opts \\ + --multiboot-command-line='\${kernel-command-line}' \\ + --host-priv-port='\${host-port}' \\ +--- util/grub.d/10_illumos.in ++++ util/grub.d/10_illumos.in +@@ -46,6 +46,7 @@ + ISADIR= + fi + zfs-bootfs $($grub_mkrelpath /) ZFS_BOOTFS ++ echo '$(echo "$message" | grub_quote)' + multiboot $($grub_mkrelpath /platform/i86pc/kernel)/\$ISADIR/unix /platform/i86pc/kernel/\$ISADIR/unix -B \$ZFS_BOOTFS,console=text + module $($grub_mkrelpath /platform/i86pc)/\$ISADIR/boot_archive /platform/i86pc/\$ISADIR/boot_archive + } +--- util/grub.d/10_kfreebsd.in ++++ util/grub.d/10_kfreebsd.in +@@ -100,7 +100,7 @@ + printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" + message="$(gettext_printf "Loading kernel of FreeBSD %s ..." ${version})" + sed "s/^/$submenu_indentation/" << EOF +- echo '$message' ++ echo '$(echo "$message" | grub_quote)' + kfreebsd ${rel_dirname}/${basename} ${args} + EOF + +--- util/grub.d/10_linux.in ++++ util/grub.d/10_linux.in +@@ -134,14 +134,14 @@ + fi + message="$(gettext_printf "Loading Linux %s ..." ${version})" + sed "s/^/$submenu_indentation/" << EOF +- echo '$message' ++ echo '$(echo "$message" | grub_quote)' + linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} + EOF + if test -n "${initrd}" ; then + # TRANSLATORS: ramdisk isn't identifier. Should be translated. + message="$(gettext_printf "Loading initial ramdisk ...")" + sed "s/^/$submenu_indentation/" << EOF +- echo '$message' ++ echo '$(echo "$message" | grub_quote)' + initrd ${rel_dirname}/${initrd} + EOF + fi +--- util/grub.d/20_linux_xen.in ++++ util/grub.d/20_linux_xen.in +@@ -120,16 +120,16 @@ + xmessage="$(gettext_printf "Loading Xen %s ..." ${xen_version})" + lmessage="$(gettext_printf "Loading Linux %s ..." ${version})" + sed "s/^/$submenu_indentation/" << EOF +- echo '$xmessage' ++ echo '$(echo "$xmessage" | grub_quote)' + multiboot ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} +- echo '$lmessage' ++ echo '$(echo "$lmessage" | grub_quote)' + module ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args} + EOF + if test -n "${initrd}" ; then + # TRANSLATORS: ramdisk isn't identifier. Should be translated. + message="$(gettext_printf "Loading initial ramdisk ...")" + sed "s/^/$submenu_indentation/" << EOF +- echo '$message' ++ echo '$(echo "$message" | grub_quote)' + module ${rel_dirname}/${initrd} + EOF + fi diff --git a/sys-boot/grub/files/grub-2.00-dmraid.patch b/sys-boot/grub/files/grub-2.00-dmraid.patch new file mode 100644 index 00000000..c39267ae --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-dmraid.patch @@ -0,0 +1,28 @@ +Fix DMRAID partition handling + +https://bugs.gentoo.org/show_bug.cgi?id=430748 +https://savannah.gnu.org/bugs/?37073 +http://bzr.savannah.gnu.org/lh/grub/trunk/grub/revision/4858 + +=== modified file 'util/getroot.c' +--- util/getroot.c 2013-04-12 20:37:59 +0000 ++++ util/getroot.c 2013-04-15 06:37:13 +0000 +@@ -1956,6 +1956,7 @@ + grub_util_info ("dm_tree_find_node failed"); + goto devmapper_out; + } ++ reiterate: + node_uuid = dm_tree_node_get_uuid (node); + if (! node_uuid) + { +@@ -2030,6 +2031,9 @@ + goto devmapper_out; + } + mapper_name = child_name; ++ *is_part = 1; ++ node = child; ++ goto reiterate; + + devmapper_out: + if (! mapper_name && node) + diff --git a/sys-boot/grub/files/grub-2.00-freebsd.patch b/sys-boot/grub/files/grub-2.00-freebsd.patch new file mode 100644 index 00000000..bcfbf263 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-freebsd.patch @@ -0,0 +1,382 @@ +Taken from +http://bzr.savannah.gnu.org/lh/grub/trunk/grub/revision/4556 +http://bzr.savannah.gnu.org/lh/grub/trunk/grub/revision/4584 +http://bzr.savannah.gnu.org/lh/grub/trunk/grub/revision/4624 +http://bzr.savannah.gnu.org/lh/grub/trunk/grub/revision/4625 + +diff -Nur grub-2.00.orig/grub-core/loader/i386/bsd.c grub-2.00/grub-core/loader/i386/bsd.c +--- grub-2.00.orig/grub-core/loader/i386/bsd.c 2012-06-07 22:06:00.000000000 +0900 ++++ grub-2.00/grub-core/loader/i386/bsd.c 2013-01-04 19:50:55.000000000 +0900 +@@ -1309,7 +1309,7 @@ + && phdr->p_type != PT_DYNAMIC) + return 0; + +- paddr = phdr->p_paddr & 0xFFFFFF; ++ paddr = phdr->p_paddr & 0xFFFFFFF; + + if (paddr < kern_start) + kern_start = paddr; +@@ -1333,7 +1333,7 @@ + } + + *do_load = 1; +- phdr->p_paddr &= 0xFFFFFF; ++ phdr->p_paddr &= 0xFFFFFFF; + paddr = phdr->p_paddr; + + *addr = (grub_addr_t) (paddr - kern_start + (grub_uint8_t *) kern_chunk_src); +@@ -1351,7 +1351,7 @@ + && phdr->p_type != PT_DYNAMIC) + return 0; + +- paddr = phdr->p_paddr & 0xffffff; ++ paddr = phdr->p_paddr & 0xfffffff; + + if (paddr < kern_start) + kern_start = paddr; +@@ -1375,7 +1375,7 @@ + } + + *do_load = 1; +- paddr = phdr->p_paddr & 0xffffff; ++ paddr = phdr->p_paddr & 0xfffffff; + + *addr = (grub_addr_t) (paddr - kern_start + (grub_uint8_t *) kern_chunk_src); + +@@ -1394,7 +1394,7 @@ + { + grub_relocator_chunk_t ch; + +- entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF; ++ entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFFF; + err = grub_elf32_phdr_iterate (elf, filename, + grub_bsd_elf32_size_hook, NULL); + if (err) +diff -Nur grub-2.00.orig/util/grub-mkconfig_lib.in grub-2.00/util/grub-mkconfig_lib.in +--- grub-2.00.orig/util/grub-mkconfig_lib.in 2012-06-28 00:27:53.000000000 +0900 ++++ grub-2.00/util/grub-mkconfig_lib.in 2013-01-04 19:50:55.000000000 +0900 +@@ -349,3 +349,10 @@ + cat + fi + } ++ ++grub_tab=" " ++ ++grub_add_tab () { ++ sed -e "s/^/$grub_tab/" ++} ++ +diff -Nur grub-2.00.orig/util/grub.d/10_hurd.in grub-2.00/util/grub.d/10_hurd.in +--- grub-2.00.orig/util/grub.d/10_hurd.in 2012-03-05 05:10:04.000000000 +0900 ++++ grub-2.00/util/grub.d/10_hurd.in 2013-01-04 19:50:55.000000000 +0900 +@@ -108,7 +108,7 @@ + EOF + fi + +- prepare_grub_to_access_device "${GRUB_DEVICE_BOOT}" | sed -e "s/^/\t/"|sed "s/^/$submenu_indentation/" ++ prepare_grub_to_access_device "${GRUB_DEVICE_BOOT}" | grub_add_tab|sed "s/^/$submenu_indentation/" + message="$(gettext_printf "Loading GNU Mach ...")" + + if [ x$type = xrecovery ] ; then +@@ -122,9 +122,9 @@ + EOF + + if [ x$type != xrecovery ] ; then +- save_default_entry | sed -e "s/^/\t/"| sed "s/^/$submenu_indentation/" ++ save_default_entry | grub_add_tab| sed "s/^/$submenu_indentation/" + fi +- prepare_grub_to_access_device "${GRUB_DEVICE}" | sed -e "s/^/\t/"| sed "s/^/$submenu_indentation/" ++ prepare_grub_to_access_device "${GRUB_DEVICE}" | grub_add_tab| sed "s/^/$submenu_indentation/" + message="$(gettext_printf "Loading the Hurd ...")" + if [ x$type = xrecovery ] ; then + opts= +@@ -158,7 +158,7 @@ + + if [ "x$is_first_entry" = xtrue ]; then + hurd_entry "$kernel" simple +- submenu_indentation="\t" ++ submenu_indentation="$grub_tab" + + # TRANSLATORS: %s is replaced with an OS name + echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' \$menuentry_id_option 'gnuhurd-advanced-$(grub_get_device_id "${GRUB_DEVICE_BOOT}")' {" +diff -Nur grub-2.00.orig/util/grub.d/10_illumos.in grub-2.00/util/grub.d/10_illumos.in +--- grub-2.00.orig/util/grub.d/10_illumos.in 2012-03-05 04:03:38.000000000 +0900 ++++ grub-2.00/util/grub.d/10_illumos.in 2013-01-04 19:50:55.000000000 +0900 +@@ -35,8 +35,8 @@ + esac + + echo "menuentry '$(echo "$OS" | grub_quote)' ${CLASS} \$menuentry_id_option 'illumos-$(grub_get_device_id "${GRUB_DEVICE_BOOT}")' {" +-save_default_entry | sed -e "s/^/\t/" +-prepare_grub_to_access_device "${GRUB_DEVICE_BOOT}" | sed -e "s/^/\t/" ++save_default_entry | grub_add_tab ++prepare_grub_to_access_device "${GRUB_DEVICE_BOOT}" | grub_add_tab + message="$(gettext_printf "Loading kernel of Illumos ...")" + cat << EOF + insmod gzio +diff -Nur grub-2.00.orig/util/grub.d/10_kfreebsd.in grub-2.00/util/grub.d/10_kfreebsd.in +--- grub-2.00.orig/util/grub.d/10_kfreebsd.in 2012-03-05 06:02:30.000000000 +0900 ++++ grub-2.00/util/grub.d/10_kfreebsd.in 2013-01-04 19:50:55.000000000 +0900 +@@ -54,7 +54,7 @@ + fi + + if [ -z "${prepare_module_dir_cache}" ]; then +- prepare_module_dir_cache="$(prepare_grub_to_access_device $(grub-probe -t device "${module_dir}") | sed -e "s/^/\t/")" ++ prepare_module_dir_cache="$(prepare_grub_to_access_device $(${grub_probe} -t device "${module_dir}") | grub_add_tab)" + fi + + printf '%s\n' "${prepare_module_dir_cache}" +@@ -91,10 +91,10 @@ + echo "menuentry '$(echo "$OS" | grub_quote)' ${CLASS} \$menuentry_id_option 'kfreebsd-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + fi + if [ x$type != xrecovery ] ; then +- save_default_entry | sed -e "s/^/\t/" | sed "s/^/$submenu_indentation/" ++ save_default_entry | grub_add_tab | sed "s/^/$submenu_indentation/" + fi + if [ -z "${prepare_boot_cache}" ]; then +- prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" ++ prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | grub_add_tab)" + fi + + printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" +@@ -112,7 +112,7 @@ + + load_kfreebsd_module acpi true + +- for abstraction in dummy $(grub-probe -t abstraction --device ${GRUB_DEVICE}) ; do ++ for abstraction in dummy $(${grub_probe} -t abstraction --device ${GRUB_DEVICE}) ; do + case $abstraction in + lvm) load_kfreebsd_module geom_linux_lvm false ;; + esac +@@ -122,10 +122,10 @@ + zfs) + load_kfreebsd_module opensolaris false + +- ls "${dirname}/zfs/zpool.cache" > /dev/null ++ ls "/boot/zfs/zpool.cache" > /dev/null + printf '%s\n' "${prepare_boot_cache}" + sed "s/^/$submenu_indentation/" << EOF +- kfreebsd_module ${rel_dirname}/zfs/zpool.cache type=/boot/zfs/zpool.cache ++ kfreebsd_module $(make_system_path_relative_to_its_root /boot)/zfs/zpool.cache type=/boot/zfs/zpool.cache + EOF + ;; + esac +@@ -179,7 +179,7 @@ + case ${GRUB_FS} in + zfs) + # zpool name +- kfreebsd_device=$(grub-probe -t fs_label --device ${GRUB_DEVICE}) ++ kfreebsd_device=$(${grub_probe} -t fs_label --device ${GRUB_DEVICE}) + # filesystem name (empty string for the main filesystem) + kfreebsd_device="${kfreebsd_device}$(${grub_mkrelpath} / | sed -e "s,/*@$,,")" + ;; +@@ -213,7 +213,7 @@ + + if [ "x$is_first_entry" = xtrue ]; then + kfreebsd_entry "${OS}" "${version}" simple +- submenu_indentation="\t" ++ submenu_indentation="$grub_tab" + + if [ -z "$boot_device_id" ]; then + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" +diff -Nur grub-2.00.orig/util/grub.d/10_linux.in grub-2.00/util/grub.d/10_linux.in +--- grub-2.00.orig/util/grub.d/10_linux.in 2012-04-19 06:24:38.000000000 +0900 ++++ grub-2.00/util/grub.d/10_linux.in 2013-01-04 19:50:55.000000000 +0900 +@@ -101,7 +101,7 @@ + echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + fi + if [ x$type != xrecovery ] ; then +- save_default_entry | sed -e "s/^/\t/" ++ save_default_entry | grub_add_tab + fi + + # Use ELILO's generic "efifb" when it's known to be available. +@@ -123,12 +123,12 @@ + + if [ x$dirname = x/ ]; then + if [ -z "${prepare_root_cache}" ]; then +- prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/")" ++ prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab)" + fi + printf '%s\n' "${prepare_root_cache}" | sed "s/^/$submenu_indentation/" + else + if [ -z "${prepare_boot_cache}" ]; then +- prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" ++ prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | grub_add_tab)" + fi + printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" + fi +@@ -230,7 +230,7 @@ + linux_entry "${OS}" "${version}" simple \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + +- submenu_indentation="\t" ++ submenu_indentation="$grub_tab" + + if [ -z "$boot_device_id" ]; then + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" +diff -Nur grub-2.00.orig/util/grub.d/10_netbsd.in grub-2.00/util/grub.d/10_netbsd.in +--- grub-2.00.orig/util/grub.d/10_netbsd.in 2012-03-05 04:47:35.000000000 +0900 ++++ grub-2.00/util/grub.d/10_netbsd.in 2013-01-04 19:50:55.000000000 +0900 +@@ -77,10 +77,10 @@ + prepare_grub_to_access_device $(${grub_probe} -t device "${kmodule}") | sed -e 's,^, ,' + case "${loader}" in + knetbsd) +- printf "\tknetbsd_module_elf %s\n" "${kmodule_rel}" ++ printf "$grub_tabknetbsd_module_elf %s\n" "${kmodule_rel}" + ;; + multiboot) +- printf "\tmodule %s\n" "${kmodule_rel}" ++ printf "$grub_tabmodule %s\n" "${kmodule_rel}" + ;; + esac + } +@@ -121,11 +121,11 @@ + printf "%s\n" "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" + case "${loader}" in + knetbsd) +- printf "\tknetbsd %s -r %s %s\n" \ ++ printf "$grub_tabknetbsd %s -r %s %s\n" \ + "${kernel}" "${kroot_device}" "${GRUB_CMDLINE_NETBSD} ${args}" | sed "s/^/$submenu_indentation/" + ;; + multiboot) +- printf "\tmultiboot %s %s root=%s %s\n" \ ++ printf "$grub_tabmultiboot %s %s root=%s %s\n" \ + "${kernel}" "${kernel}" "${kroot_device}" "${GRUB_CMDLINE_NETBSD} ${args}" | sed "s/^/$submenu_indentation/" + ;; + esac +@@ -159,7 +159,7 @@ + + if [ "x$is_first_entry" = xtrue ]; then + netbsd_entry "knetbsd" "$k" simple "${GRUB_CMDLINE_NETBSD_DEFAULT}" +- submenu_indentation="\t" ++ submenu_indentation="$grub_tab" + + if [ -z "$boot_device_id" ]; then + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" +diff -Nur grub-2.00.orig/util/grub.d/10_windows.in grub-2.00/util/grub.d/10_windows.in +--- grub-2.00.orig/util/grub.d/10_windows.in 2012-03-05 06:11:43.000000000 +0900 ++++ grub-2.00/util/grub.d/10_windows.in 2013-01-04 19:50:55.000000000 +0900 +@@ -45,7 +45,7 @@ + sort | uniq | wc -l`" = 1 || return 1 + + # Search 'default=PARTITION' +- get_os_name_from_boot_ini_part=`sed -n 's,^default=,,p' "$1" | sed 's,\\\\,/,g;s,[ \t\r]*$,,;1q'` ++ get_os_name_from_boot_ini_part=`sed -n 's,^default=,,p' "$1" | sed 's,\\\\,/,g;s,[ $grub_tab\r]*$,,;1q'` + test -n "$get_os_name_from_boot_ini_part" || return 1 + + # Search 'PARTITION="NAME" ...' +@@ -87,8 +87,8 @@ + menuentry '$(echo "$OS" | grub_quote)' \$menuentry_id_option '$osid-$(grub_get_device_id "${dev}")' { + EOF + +- save_default_entry | sed -e 's,^,\t,' +- prepare_grub_to_access_device "$dev" | sed 's,^,\t,' ++ save_default_entry | sed -e 's,^,$grub_tab,' ++ prepare_grub_to_access_device "$dev" | sed 's,^,$grub_tab,' + test -z "$needmap" || cat <<EOF + drivemap -s (hd0) \$root + EOF +diff -Nur grub-2.00.orig/util/grub.d/10_xnu.in grub-2.00/util/grub.d/10_xnu.in +--- grub-2.00.orig/util/grub.d/10_xnu.in 2012-05-29 19:31:03.000000000 +0900 ++++ grub-2.00/util/grub.d/10_xnu.in 2013-01-04 19:50:55.000000000 +0900 +@@ -39,8 +39,8 @@ + cat << EOF + menuentry '$(echo "Darwin/Mac OS X $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${GRUB_DEVICE}")' { + EOF +- save_default_entry | sed -e "s/^/ /" +- prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/ /" ++ save_default_entry | grub_add_tab ++ prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab + cat << EOF + load_video + set do_resume=0 +diff -Nur grub-2.00.orig/util/grub.d/20_linux_xen.in grub-2.00/util/grub.d/20_linux_xen.in +--- grub-2.00.orig/util/grub.d/20_linux_xen.in 2012-06-04 04:57:42.000000000 +0900 ++++ grub-2.00/util/grub.d/20_linux_xen.in 2013-01-04 19:50:55.000000000 +0900 +@@ -110,11 +110,11 @@ + echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'xen-gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + fi + if [ x$type != xrecovery ] ; then +- save_default_entry | sed -e "s/^/\t/" | sed "s/^/$submenu_indentation/" ++ save_default_entry | grub_add_tab | sed "s/^/$submenu_indentation/" + fi + + if [ -z "${prepare_boot_cache}" ]; then +- prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" ++ prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | grub_add_tab)" + fi + printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" + xmessage="$(gettext_printf "Loading Xen %s ..." ${xen_version})" +@@ -236,7 +236,7 @@ + linux_entry "${OS}" "${version}" "${xen_version}" simple \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" "${GRUB_CMDLINE_XEN} ${GRUB_CMDLINE_XEN_DEFAULT}" + +- submenu_indentation="\t\t" ++ submenu_indentation="$grub_tab$grub_tab" + + if [ -z "$boot_device_id" ]; then + boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" +diff -Nur grub-2.00.orig/util/grub.d/30_os-prober.in grub-2.00/util/grub.d/30_os-prober.in +--- grub-2.00.orig/util/grub.d/30_os-prober.in 2012-03-05 05:52:03.000000000 +0900 ++++ grub-2.00/util/grub.d/30_os-prober.in 2013-01-04 19:50:55.000000000 +0900 +@@ -54,8 +54,8 @@ + cat << EOF + menuentry '$(echo "${LONGNAME} $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' { + EOF +- save_default_entry | sed -e "s/^/\t/" +- prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" ++ save_default_entry | grub_add_tab ++ prepare_grub_to_access_device ${DEVICE} | grub_add_tab + cat << EOF + load_video + set do_resume=0 +@@ -126,8 +126,8 @@ + cat << EOF + menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' { + EOF +- save_default_entry | sed -e "s/^/\t/" +- prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" ++ save_default_entry | grub_add_tab ++ prepare_grub_to_access_device ${DEVICE} | grub_add_tab + + case ${LONGNAME} in + Windows\ Vista*|Windows\ 7*|Windows\ Server\ 2008*) +@@ -181,14 +181,14 @@ + used_osprober_linux_ids="$used_osprober_linux_ids 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id'" + + if [ -z "${prepare_boot_cache}" ]; then +- prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | sed -e "s/^/\t/")" ++ prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)" + fi + + if [ "x$is_first_entry" = xtrue ]; then + cat << EOF + menuentry '$(echo "$OS" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' { + EOF +- save_default_entry | sed -e "s/^/\t/" ++ save_default_entry | grub_add_tab + printf '%s\n' "${prepare_boot_cache}" + cat << EOF + linux ${LKERNEL} ${LPARAMS} +@@ -208,8 +208,8 @@ + cat << EOF + menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' { + EOF +- save_default_entry | sed -e "s/^/\t\t/" +- printf '%s\n' "${prepare_boot_cache}" | sed -e "s/^/\t/" ++ save_default_entry | sed -e "s/^/$grub_tab$grub_tab/" ++ printf '%s\n' "${prepare_boot_cache}" | grub_add_tab + cat << EOF + linux ${LKERNEL} ${LPARAMS} + EOF +@@ -243,8 +243,8 @@ + cat << EOF + menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' { + EOF +- save_default_entry | sed -e "s/^/\t/" +- prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" ++ save_default_entry | grub_add_tab ++ prepare_grub_to_access_device ${DEVICE} | grub_add_tab + grub_device="`${grub_probe} --device ${DEVICE} --target=drive`" + mach_device="`echo "${grub_device}" | sed -e 's/(\(hd.*\),msdos\(.*\))/\1s\2/'`" + grub_fs="`${grub_probe} --device ${DEVICE} --target=fs`" diff --git a/sys-boot/grub/files/grub-2.00-genkernel-initramfs-single.patch b/sys-boot/grub/files/grub-2.00-genkernel-initramfs-single.patch new file mode 100644 index 00000000..95a247e0 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-genkernel-initramfs-single.patch @@ -0,0 +1,11 @@ +--- grub-2.00.orig/util/grub.d/10_linux.in ++++ grub-2.00/util/grub.d/10_linux.in +@@ -243,7 +243,7 @@ while [ "x$list" != "x" ] ; do + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then + linux_entry "${OS}" "${version}" recovery \ +- "single ${GRUB_CMDLINE_LINUX}" ++ "single init_opts=single ${GRUB_CMDLINE_LINUX/splash=silent/splash=verbose}" + fi + + list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '` diff --git a/sys-boot/grub/files/grub-2.00-hardcoded-awk.patch b/sys-boot/grub/files/grub-2.00-hardcoded-awk.patch new file mode 100644 index 00000000..8019a3c7 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-hardcoded-awk.patch @@ -0,0 +1,15 @@ +https://bugs.gentoo.org/show_bug.cgi?id=424137 +https://savannah.gnu.org/bugs/?37558 +https://code.google.com/p/original-mawk/issues/detail?id=17 +--- grub-core/Makefile.am 2012-07-07 12:29:01 +0000 ++++ grub-core/Makefile.am 2012-10-12 13:04:02 +0000 +@@ -349,7 +349,7 @@ + + # generate global module dependencies list + moddep.lst: syminfo.lst genmoddep.awk video.lst +- cat $< | sort | awk -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1) ++ cat $< | sort | $(AWK) -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1) + platform_DATA += moddep.lst + CLEANFILES += config.log syminfo.lst moddep.lst + + diff --git a/sys-boot/grub/files/grub-2.00-no-gets.patch b/sys-boot/grub/files/grub-2.00-no-gets.patch new file mode 100644 index 00000000..c21d4b97 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-no-gets.patch @@ -0,0 +1,22 @@ +hack until gzip pulls a newer gnulib version + +From 66712c23388e93e5c518ebc8515140fa0c807348 Mon Sep 17 00:00:00 2001 +From: Eric Blake <eblake@redhat.com> +Date: Thu, 29 Mar 2012 13:30:41 -0600 +Subject: [PATCH] stdio: don't assume gets any more + +Gnulib intentionally does not have a gets module, and now that C11 +and glibc have dropped it, we should be more proactive about warning +any user on a platform that still has a declaration of this dangerous +interface. + +--- a/grub-core/gnulib/stdio.in.h ++++ b/grub-core/gnulib/stdio.in.h +@@ -125,7 +125,6 @@ + so any use of gets warrants an unconditional warning. Assume it is + always declared, since it is required by C89. */ + #undef gets +-_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); + + #if @GNULIB_FOPEN@ + # if @REPLACE_FOPEN@ diff --git a/sys-boot/grub/files/grub-2.00-os-prober-efi-system.patch b/sys-boot/grub/files/grub-2.00-os-prober-efi-system.patch new file mode 100644 index 00000000..7e0888a8 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-os-prober-efi-system.patch @@ -0,0 +1,27 @@ +=== modified file 'util/grub.d/30_os-prober.in' +--- util/grub.d/30_os-prober.in 2013-04-19 08:08:46 +0000 ++++ util/grub.d/30_os-prober.in 2013-05-31 16:29:03 +0000 +@@ -149,6 +149,22 @@ + } + EOF + ;; ++ efi) ++ ++ EFIPATH=${DEVICE#*@} ++ DEVICE=${DEVICE%@*} ++ onstr="$(gettext_printf "(on %s)" "${DEVICE}")" ++ cat << EOF ++menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-efi-$(grub_get_device_id "${DEVICE}")' { ++EOF ++ save_default_entry | sed -e "s/^/\t/" ++ prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" ++ ++ cat <<EOF ++ chainloader ${EFIPATH} ++} ++EOF ++ ;; + linux) + if [ "x$BTRFS" = "xbtrfs" ]; then + LINUXPROBED="`linux-boot-prober btrfs ${BTRFSuuid} ${BTRFSsubvol} 2> /dev/null | tr ' ' '^' | paste -s -d ' '`" + diff --git a/sys-boot/grub/files/grub-2.00-parallel-make.patch b/sys-boot/grub/files/grub-2.00-parallel-make.patch new file mode 100644 index 00000000..03d634bb --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-parallel-make.patch @@ -0,0 +1,46 @@ +Fix parallel make problems. +Upstream changesets 4547, 4552, 4578. +--- gentpl.py ++++ gentpl.py +@@ -484,10 +484,10 @@ + def installdir(default="bin"): + return "[+ IF installdir +][+ installdir +][+ ELSE +]" + default + "[+ ENDIF +]" + +-def manpage(): ++def manpage(adddeps): + r = "if COND_MAN_PAGES\n" + r += gvar_add("man_MANS", "[+ name +].[+ mansection +]\n") +- r += rule("[+ name +].[+ mansection +]", "[+ name +]", """ ++ r += rule("[+ name +].[+ mansection +]", "[+ name +] " + adddeps, """ + chmod a+x [+ name +] + PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=[+ mansection +] -i $(top_srcdir)/docs/man/[+ name +].h2m -o $@ [+ name +] + """) +@@ -503,7 +503,7 @@ + r += gvar_add("TESTS", "[+ name +]") + r += "[+ ELSE +]" + r += var_add(installdir() + "_PROGRAMS", "[+ name +]") +- r += "[+ IF mansection +]" + manpage() + "[+ ENDIF +]" ++ r += "[+ IF mansection +]" + manpage("") + "[+ ENDIF +]" + r += "[+ ENDIF +]" + + r += var_set(cname() + "_SOURCES", platform_sources(platform)) +@@ -532,7 +532,7 @@ + r += gvar_add ("TESTS", "[+ name +]") + r += "[+ ELSE +]" + r += var_add(installdir() + "_SCRIPTS", "[+ name +]") +- r += "[+ IF mansection +]" + manpage() + "[+ ENDIF +]" ++ r += "[+ IF mansection +]" + manpage("grub-mkconfig_lib") + "[+ ENDIF +]" + r += "[+ ENDIF +]" + + r += rule("[+ name +]", platform_sources(platform) + " $(top_builddir)/config.status", """ +--- grub-core/Makefile.am ++++ grub-core/Makefile.am +@@ -63,7 +63,7 @@ + rs_decoder.S: $(srcdir)/lib/reed_solomon.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Os -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3 -ffreestanding + +-kern/i386/pc/startup.S: $(builddir)/rs_decoder.S ++boot/i386/pc/startup_raw.S: $(builddir)/rs_decoder.S + boot/mips/loongson/fwstart.S: $(builddir)/sm712_start.S + + CLEANFILES += grub_script.yy.c grub_script.yy.h diff --git a/sys-boot/grub/files/grub-2.00-rogentos-patch.patch b/sys-boot/grub/files/grub-2.00-rogentos-patch.patch new file mode 100644 index 00000000..f3238628 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-rogentos-patch.patch @@ -0,0 +1,10 @@ +--- grub-2.00.orig/util/grub.d/10_linux.in 2012-09-09 23:41:17.299578772 +0000 ++++ grub-2.00/util/grub.d/10_linux.in 2012-09-09 23:40:11.014407451 +0000 +@@ -25,6 +25,7 @@ datarootdir="@datarootdir@" + + export TEXTDOMAIN=@PACKAGE@ + export TEXTDOMAINDIR="@localedir@" ++export GRUB_DISTRIBUTOR=Rogentos + + CLASS="--class gnu-linux --class gnu --class os" + diff --git a/sys-boot/grub/files/grub-2.00-secureboot-user-sign-2.patch b/sys-boot/grub/files/grub-2.00-secureboot-user-sign-2.patch new file mode 100644 index 00000000..6882d1f4 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-secureboot-user-sign-2.patch @@ -0,0 +1,64 @@ +diff -Nurp grub-2.00.orig/util/grub-install.in grub-2.00/util/grub-install.in +--- grub-2.00.orig/util/grub-install.in 2012-06-26 23:31:03.000000000 +0200 ++++ grub-2.00/util/grub-install.in 2012-12-28 10:11:09.515872080 +0100 +@@ -821,12 +821,60 @@ elif [ x"${grub_modinfo_target_cpu}-${gr + gettext "You will have to set \`SystemPartition' and \`OSLoader' manually." 1>&2 + echo 1>&2 + elif [ x"$grub_modinfo_platform" = xefi ]; then ++ ++ # sign the efi file with the User SecureBoot key ++ _sign_grub_efi() { ++ local _image="${1}" ++ local _image_dir="$(dirname "${_image}")" ++ local _image_name="$(basename "${_image}")" ++ ++ case "$host_os" in ++ linux*) ++ modprobe -q efivars 2>/dev/null || true ;; ++ esac ++ ++ local _private="/boot/SecureBoot/user-private.key" ++ local _public="/boot/SecureBoot/user-public.crt" ++ local _shim_dir="/usr/share/shim-signed-*" ++ if test -f "${_private}" && test -f "${_public}"; then ++ echo "SecureBoot signing ${_image}" ++ sbsign --key "${_private}" --cert "${_public}" \ ++ --output "${_image}.signed" \ ++ "${_image}" && \ ++ mv "${_image}.signed" "${_image}" && \ ++ cp ${_shim_dir}/*.efi "${_image_dir}/" ++ ++ # if the image is called bootx64.efi, we need to rename it into ++ # grubx64.efi and place shim.efi there. ++ if test "${_image_name}" = "bootx64.efi" || test "${_image_name}" = "BOOTX64.EFI"; then ++ mv "${_image}" "${_image_dir}/grubx64.efi" ++ mv "${_image_dir}/shim.efi" "${_image_dir}/${_image_name}" ++ else ++ # otherwise, if it's named grubx64.efi, we just need to move ++ # shim.efi to bootx64.efi ++ mv "${_image_dir}/shim.efi" "${_image_dir}/bootx64.efi" ++ if test "${_image_name}" != "grubx64.efi" && test "${_image_name}" != "GRUBX64.EFI"; then ++ mv "${_image_dir}/${_image_name}" "${_image_dir}/grubx64.efi" ++ fi ++ # and then change efi_file ++ efi_file="bootx64.efi" ++ fi ++ else ++ echo "Cannot sign ${_image} for SecureBoot" 1>&2 ++ echo "RogentOS keypair at $(basename ${_private}) not found" 1>&2 ++ fi ++ } ++ + cp "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" "${efidir}/${efi_file}" ++ _efi_grub_file="${efidir}/${efi_file}" + # For old macs. Suggested by Peter Jones. + if [ x$grub_modinfo_target_cpu = xi386 ]; then + cp "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" "${efidir}/boot.efi" ++ _efi_grub_file="${efidir}/boot.efi" + fi + ++ _sign_grub_efi "${_efi_grub_file}" ++ + # Try to make this image bootable using the EFI Boot Manager, if available. + efibootmgr="`which efibootmgr`" + if test "$removable" = no && test -n "$efi_distributor" && \ diff --git a/sys-boot/grub/files/grub-2.00-secureboot-user-sign.patch b/sys-boot/grub/files/grub-2.00-secureboot-user-sign.patch new file mode 100644 index 00000000..6c02cbd4 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-secureboot-user-sign.patch @@ -0,0 +1,42 @@ +--- a/util/grub-install.in ++++ b/util/grub-install.in +@@ -821,12 +821,39 @@ elif [ x"${grub_modinfo_target_cpu}-${gr + gettext "You will have to set \`SystemPartition' and \`OSLoader' manually." 1>&2 + echo 1>&2 + elif [ x"$grub_modinfo_platform" = xefi ]; then ++ ++ # sign the efi file with the User SecureBoot key ++ _sign_grub_efi() { ++ local _image="${1}" ++ case "$host_os" in ++ linux*) ++ modprobe -q efivars 2>/dev/null || true ;; ++ esac ++ ++ local _private="/boot/SecureBoot/user-private.key" ++ local _public="/boot/SecureBoot/user-public.crt" ++ if test -f "${_private}" && test -f "${_public}"; then ++ echo "SecureBoot signing ${_image}" ++ sbsign --key "${_private}" --cert "${_public}" \ ++ --output "${_image}.signed" \ ++ "${_image}" && \ ++ mv "${_image}.signed" "${_image}" ++ else ++ echo "Cannot sign ${_image} for SecureBoot" 1>&2 ++ echo "RogentOS keypair at $(basename ${_private}) not found" 1>&2 ++ fi ++ } ++ + cp "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" "${efidir}/${efi_file}" ++ _efi_grub_file="${efidir}/${efi_file}" + # For old macs. Suggested by Peter Jones. + if [ x$grub_modinfo_target_cpu = xi386 ]; then + cp "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" "${efidir}/boot.efi" ++ _efi_grub_file="${efidir}/boot.efi" + fi + ++ _sign_grub_efi "${_efi_grub_file}" ++ + # Try to make this image bootable using the EFI Boot Manager, if available. + efibootmgr="`which efibootmgr`" + if test "$removable" = no && test -n "$efi_distributor" && \ diff --git a/sys-boot/grub/files/grub-2.00-texinfo.patch b/sys-boot/grub/files/grub-2.00-texinfo.patch new file mode 100644 index 00000000..803f3cbc --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-texinfo.patch @@ -0,0 +1,16 @@ +Fix for texinfo-5.1 + +=== modified file 'docs/grub-dev.texi' +--- docs/grub-dev.texi 2012-05-22 07:15:28 +0000 ++++ docs/grub-dev.texi 2013-04-08 13:23:07 +0000 +@@ -1394,8 +1394,8 @@ + + @node Bitmap API + @section Bitmap API +-@itemize + @subsection grub_video_bitmap_create ++@itemize + @item Prototype: + @example + grub_err_t grub_video_bitmap_create (struct grub_video_bitmap **bitmap, unsigned int width, unsigned int height, enum grub_video_blit_format blit_format) + diff --git a/sys-boot/grub/files/grub-2.00-tftp-endian.patch b/sys-boot/grub/files/grub-2.00-tftp-endian.patch new file mode 100644 index 00000000..f4e56445 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-tftp-endian.patch @@ -0,0 +1,24 @@ +https://bugs.gentoo.org/show_bug.cgi?id=438612 + +=== modified file 'grub-core/net/tftp.c' +--- grub-core/net/tftp.c 2012-06-22 20:04:16 +0000 ++++ grub-core/net/tftp.c 2012-07-02 09:22:50 +0000 +@@ -143,7 +143,7 @@ + + tftph_ack = (struct tftphdr *) nb_ack.data; + tftph_ack->opcode = grub_cpu_to_be16 (TFTP_ACK); +- tftph_ack->u.ack.block = block; ++ tftph_ack->u.ack.block = grub_cpu_to_be16 (block); + + err = grub_net_send_udp_packet (data->sock, &nb_ack); + if (err) +@@ -225,7 +225,7 @@ + grub_priority_queue_pop (data->pq); + + if (file->device->net->packs.count < 50) +- err = ack (data, tftph->u.data.block); ++ err = ack (data, data->block + 1); + else + { + file->device->net->stall = 1; + diff --git a/sys-boot/grub/files/grub-2.00-vga-deprecated-not-yet.patch b/sys-boot/grub/files/grub-2.00-vga-deprecated-not-yet.patch new file mode 100644 index 00000000..3859bb2e --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-vga-deprecated-not-yet.patch @@ -0,0 +1,13 @@ +--- grub-2.00.orig/grub-core/loader/i386/linux.c ++++ grub-2.00/grub-core/loader/i386/linux.c +@@ -946,10 +946,6 @@ grub_cmd_linux (grub_command_t cmd __att + if (! buf) + goto fail; + +- grub_printf_ (N_("%s is deprecated. " +- "Use set gfxpayload=%s before " +- "linux command instead.\n"), +- argv[i], buf); + err = grub_env_set ("gfxpayload", buf); + grub_free (buf); + if (err) diff --git a/sys-boot/grub/files/grub-2.00-wallpaper-settings-support.patch b/sys-boot/grub/files/grub-2.00-wallpaper-settings-support.patch new file mode 100644 index 00000000..828eef72 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-wallpaper-settings-support.patch @@ -0,0 +1,14 @@ +--- grub-2.00.orig/util/grub-mkconfig.in ++++ grub-2.00/util/grub-mkconfig.in +@@ -216,7 +216,10 @@ export GRUB_DEFAULT \ + GRUB_INIT_TUNE \ + GRUB_SAVEDEFAULT \ + GRUB_ENABLE_CRYPTODISK \ +- GRUB_BADRAM ++ GRUB_BADRAM \ ++ GRUB_WALLPAPER \ ++ GRUB_COLOR_NORMAL \ ++ GRUB_COLOR_HIGHLIGHT + + if test "x${grub_cfg}" != "x"; then + rm -f "${grub_cfg}.new" diff --git a/sys-boot/grub/files/grub-2.00-zfs-feature-flag-support-r1.patch b/sys-boot/grub/files/grub-2.00-zfs-feature-flag-support-r1.patch new file mode 100644 index 00000000..b7d780f2 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-zfs-feature-flag-support-r1.patch @@ -0,0 +1,893 @@ +ZFS Feature Flag Support + +This is a monolithic version of the following commits: + +https://github.com/maxximino/grub2/commit/31a32560fd7948ae5ff5c63105d7c068de7890c8 +https://github.com/maxximino/grub2/commit/595d76e8ca0690a963f5533689de8db54ef07e75 +https://github.com/maxximino/grub2/commit/58344034e40218b20500fa2936eb4d7d019e1e88 +https://github.com/maxximino/grub2/commit/f98cb078abab2c14bb0766b5a0ceb055683dab81 +https://github.com/maxximino/grub2/commit/f12806f43a969a654dee7bb89b2e8fd5c42f0e2e + +A change was made to account for d8a0feb6 from upstream. This change prevents a +compile time failure that is caused by a change in the callback interface used +by mzap_interate(). Modifications to nvlist_find_value() were reverted to +resolve Gentoo bug #462740. This eliminated the need for the new nvpair_type() +and nvpair_value() functions. They have been removed to silence a compiler +warning and reduce the size of the patch. Further adjustments were made to +silence the following warnings: + +/var/tmp/portage/sys-boot/grub-2.00-r2/work/grub-2.00/grub-core/fs/zfs/zfs_lz4.c:77:5: +warning: "__STDC_VERSION__" is not defined [-Wundef] +/var/tmp/portage/sys-boot/grub-2.00-r2/work/grub-2.00/grub-core/fs/zfs/zfs.c:4079:3: +warning: passing argument 4 of 'mzap_iterate' from incompatible pointer type +[enabled by default] + +The initial feature flag support patches were written by Delphix while the LZ4 +support was written by Saso Kiselkov. The work porting this to GRUB2 was done +by Massimo Maggi, while the adaption to Gentoo's GRUB2 package was done by +Richard Yao. + +diff --git a/Makefile.util.def b/Makefile.util.def +index b80187c..1bf3038 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -95,6 +95,7 @@ library = { + common = grub-core/fs/zfs/zfs.c; + common = grub-core/fs/zfs/zfsinfo.c; + common = grub-core/fs/zfs/zfs_lzjb.c; ++ common = grub-core/fs/zfs/zfs_lz4.c; + common = grub-core/fs/zfs/zfs_sha256.c; + common = grub-core/fs/zfs/zfs_fletcher.c; + common = grub-core/lib/envblk.c; +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 39e77a4..1550b90 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1186,6 +1186,7 @@ module = { + name = zfs; + common = fs/zfs/zfs.c; + common = fs/zfs/zfs_lzjb.c; ++ common = fs/zfs/zfs_lz4.c; + common = fs/zfs/zfs_sha256.c; + common = fs/zfs/zfs_fletcher.c; + }; +diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c +index ba0554a..811e3df 100644 +--- a/grub-core/fs/zfs/zfs.c ++++ b/grub-core/fs/zfs/zfs.c +@@ -2,6 +2,7 @@ + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2010 Sun Microsystems, Inc. ++ * Copyright (c) 2012 by Delphix. All rights reserved. + * + * GRUB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -153,11 +154,13 @@ ZAP_LEAF_ENTRY(zap_leaf_phys_t *l, int bs, int idx) + + + /* +- * Decompression Entry - lzjb ++ * Decompression Entry - lzjb & lz4 + */ + + extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t); + ++extern grub_err_t lz4_decompress (void *, void *, grub_size_t, grub_size_t); ++ + typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start, + grub_size_t s_len, grub_size_t d_len); + typedef struct decomp_entry +@@ -263,6 +266,19 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key + grub_size_t keysize, + grub_uint64_t salt, + grub_uint64_t algo) = NULL; ++/* ++ * List of pool features that the grub implementation of ZFS supports for ++ * read. Note that features that are only required for write do not need ++ * to be listed here since grub opens pools in read-only mode. ++ */ ++static const char *spa_feature_names[] = { ++ "org.illumos:lz4_compress",NULL ++}; ++ ++static int NESTED_FUNC_ATTR ++check_feature(const char *name, grub_uint64_t val); ++static int ++check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ); + + static grub_err_t + zlib_decompress (void *s, void *d, +@@ -322,6 +338,7 @@ static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { + {"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */ + {"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */ + {"zle", zle_decompress}, /* ZIO_COMPRESS_ZLE */ ++ {"lz4", lz4_decompress}, /* ZIO_COMPRESS_LZ4 */ + }; + + static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, +@@ -482,15 +499,11 @@ uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset, + + if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) + == UBERBLOCK_MAGIC +- && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) > 0 +- && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) +- <= SPA_VERSION) +- endian = GRUB_ZFS_LITTLE_ENDIAN; ++ && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN))) ++ endian = GRUB_ZFS_LITTLE_ENDIAN; + + if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_BIG_ENDIAN) == UBERBLOCK_MAGIC +- && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) > 0 +- && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) +- <= SPA_VERSION) ++ && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN))) + endian = GRUB_ZFS_BIG_ENDIAN; + + if (endian == GRUB_ZFS_UNKNOWN_ENDIAN) +@@ -764,6 +777,99 @@ fill_vdev_info (struct grub_zfs_data *data, + } + + /* ++ * For a given XDR packed nvlist, verify the first 4 bytes and move on. ++ * ++ * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : ++ * ++ * encoding method/host endian (4 bytes) ++ * nvl_version (4 bytes) ++ * nvl_nvflag (4 bytes) ++ * encoded nvpairs: ++ * encoded size of the nvpair (4 bytes) ++ * decoded size of the nvpair (4 bytes) ++ * name string size (4 bytes) ++ * name string data (sizeof(NV_ALIGN4(string)) ++ * data type (4 bytes) ++ * # of elements in the nvpair (4 bytes) ++ * data ++ * 2 zero's for the last nvpair ++ * (end of the entire list) (8 bytes) ++ * ++ */ ++ ++/* ++ * The nvlist_next_nvpair() function returns a handle to the next nvpair in the ++ * list following nvpair. If nvpair is NULL, the first pair is returned. If ++ * nvpair is the last pair in the nvlist, NULL is returned. ++ */ ++static const char * ++nvlist_next_nvpair(const char *nvl, const char *nvpair) ++{ ++ const char *nvp; ++ int encode_size; ++ int name_len; ++ if (nvl == NULL) ++ return (NULL); ++ ++ if (nvpair == NULL) { ++ /* skip over header, nvl_version and nvl_nvflag */ ++ nvpair = nvl + 4 * 3; ++ } else { ++ /* skip to the next nvpair */ ++ encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair)); ++ nvpair += encode_size; ++ } ++ /* 8 bytes of 0 marks the end of the list */ ++ if (*(grub_uint64_t*)nvpair == 0) ++ return (NULL); ++ /*consistency checks*/ ++ if (nvpair + 4 * 3 >= nvl + VDEV_PHYS_SIZE) ++ { ++ grub_dprintf ("zfs", "nvlist overflow\n"); ++ grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); ++ return (NULL); ++ } ++ encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair)); ++ ++ nvp = nvpair + 4*2; ++ name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); ++ nvp += 4; ++ ++ nvp = nvp + ((name_len + 3) & ~3); // align ++ if (nvp + 4 >= nvl + VDEV_PHYS_SIZE ++ || encode_size < 0 ++ || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE) ++ { ++ grub_dprintf ("zfs", "nvlist overflow\n"); ++ grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); ++ return (NULL); ++ } ++ /* end consistency checks */ ++ ++ return (nvpair); ++} ++/* ++ * This function returns 0 on success and 1 on failure. On success, a string ++ * containing the name of nvpair is saved in buf. ++ */ ++static int ++nvpair_name(const char *nvp, char **buf, int* buflen) ++{ ++ int len; ++ ++ /* skip over encode/decode size */ ++ nvp += 4 * 2; ++ ++ len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); ++ nvp=nvp+4; ++ ++ *buf=(char*)nvp; ++ *buflen=len; ++ ++ return (0); ++} ++ ++/* + * Check the disk label information and retrieve needed vdev name-value pairs. + * + */ +@@ -773,7 +879,7 @@ check_pool_label (struct grub_zfs_data *data, + int *inserted) + { + grub_uint64_t pool_state, txg = 0; +- char *nvlist; ++ char *nvlist,*features; + #if 0 + char *nv; + #endif +@@ -837,13 +943,13 @@ check_pool_label (struct grub_zfs_data *data, + } + grub_dprintf ("zfs", "check 8 passed\n"); + +- if (version > SPA_VERSION) ++ if (!SPA_VERSION_IS_SUPPORTED(version)) + { + grub_free (nvlist); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "too new version %llu > %llu", + (unsigned long long) version, +- (unsigned long long) SPA_VERSION); ++ (unsigned long long) SPA_VERSION_BEFORE_FEATURES); + } + grub_dprintf ("zfs", "check 9 passed\n"); + +@@ -893,7 +999,30 @@ check_pool_label (struct grub_zfs_data *data, + grub_free (nv); + } + grub_dprintf ("zfs", "check 10 passed\n"); +- ++ if ((features=grub_zfs_nvlist_lookup_nvlist(nvlist, ZPOOL_CONFIG_FEATURES_FOR_READ))) ++ { ++ const char *nvp=NULL; ++ char *name = grub_zalloc(51); ++ char *nameptr; ++ int namelen; ++ while ((nvp = nvlist_next_nvpair(features, nvp)) != NULL) ++ { ++ nvpair_name(nvp, &nameptr,&namelen); ++ if(namelen > 50){namelen=50;} ++ grub_strncpy(name,nameptr,namelen); ++ name[namelen]=0; ++ grub_dprintf("zfs","namelen=%u str=%s\n",namelen,name); ++ if (check_feature(name,1) != 0) ++ { ++ grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name); ++ err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name); ++ grub_free(name); ++ return err; ++ } ++ } ++ grub_free(name); ++ } ++ grub_dprintf ("zfs", "check 12 passed (feature flags)\n"); + grub_free (nvlist); + + return GRUB_ERR_NONE; +@@ -3034,27 +3163,6 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + return err; + } + +-/* +- * For a given XDR packed nvlist, verify the first 4 bytes and move on. +- * +- * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : +- * +- * encoding method/host endian (4 bytes) +- * nvl_version (4 bytes) +- * nvl_nvflag (4 bytes) +- * encoded nvpairs: +- * encoded size of the nvpair (4 bytes) +- * decoded size of the nvpair (4 bytes) +- * name string size (4 bytes) +- * name string data (sizeof(NV_ALIGN4(string)) +- * data type (4 bytes) +- * # of elements in the nvpair (4 bytes) +- * data +- * 2 zero's for the last nvpair +- * (end of the entire list) (8 bytes) +- * +- */ +- + static int + nvlist_find_value (const char *nvlist_in, const char *name, + int valtype, char **val, +@@ -3386,6 +3494,10 @@ zfs_mount (grub_device_t dev) + return NULL; + } + ++ if (ub->ub_version >= SPA_VERSION_FEATURES && ++ check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian, data) != 0) ++ return NULL; ++ + /* Got the MOS. Save it at the memory addr MOS. */ + grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode, + DNODE_SIZE); +@@ -3910,6 +4022,64 @@ grub_zfs_dir (grub_device_t device, const char *path, + return grub_errno; + } + ++static int NESTED_FUNC_ATTR ++check_feature(const char *name, grub_uint64_t val) ++{ ++ int i; ++ if(val ==0) return 0; ++ if(*name==0) return 0; ++ for (i = 0; spa_feature_names[i] != NULL; i++) ++ { ++ if (grub_strcmp(name, spa_feature_names[i]) == 0) ++ return 0; ++ } ++ grub_printf("missing feature for read '%s'\n",name); ++ return 1; ++} ++ ++/* ++ * Checks whether the MOS features that are active are supported by this ++ * (GRUB's) implementation of ZFS. ++ * ++ * Return: ++ * 0: Success. ++ * errnum: Failure. ++ */ ++ ++static int ++check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ) ++{ ++ grub_uint64_t objnum; ++ grub_uint8_t errnum = 0; ++ dnode_end_t dn,mosmdn; ++ mzap_phys_t* mzp; ++ grub_zfs_endian_t endianzap; ++ int size; ++ grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t)); ++ mosmdn.endian=endian; ++ if ((errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT, ++ DMU_OT_OBJECT_DIRECTORY, &dn,data)) != 0) ++ return (errnum); ++ ++ /* ++ * Find the object number for 'features_for_read' and retrieve its ++ * corresponding dnode. Note that we don't check features_for_write ++ * because GRUB is not opening the pool for write. ++ */ ++ if ((errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0)) != 0) ++ return (errnum); ++ ++ if ((errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data)) != 0) ++ return (errnum); ++ ++ if ((errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data)) != 0) ++ return (errnum); ++ ++ size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT; ++ return (mzap_iterate(mzp,endianzap, size, check_feature)); ++} ++ ++ + #ifdef GRUB_UTIL + static grub_err_t + grub_zfs_embed (grub_device_t device __attribute__ ((unused)), +diff --git a/grub-core/fs/zfs/zfs_lz4.c b/grub-core/fs/zfs/zfs_lz4.c +new file mode 100644 +index 0000000..ff85a77 +--- /dev/null ++++ b/grub-core/fs/zfs/zfs_lz4.c +@@ -0,0 +1,321 @@ ++/* ++ * LZ4 - Fast LZ compression algorithm ++ * Header File ++ * Copyright (C) 2011-2013, Yann Collet. ++ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are ++ * met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above ++ * copyright notice, this list of conditions and the following disclaimer ++ * in the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * You can contact the author at : ++ * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html ++ * - LZ4 source repository : http://code.google.com/p/lz4/ ++ */ ++ ++#include <grub/err.h> ++#include <grub/mm.h> ++#include <grub/misc.h> ++#include <grub/types.h> ++ ++static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, ++ int isize, int maxOutputSize); ++ ++/* ++ * CPU Feature Detection ++ */ ++ ++/* 32 or 64 bits ? */ ++#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || \ ++ defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || \ ++ defined(__LP64__) || defined(_LP64)) ++#define LZ4_ARCH64 1 ++#else ++#define LZ4_ARCH64 0 ++#endif ++ ++/* ++ * Little Endian or Big Endian? ++ * Note: overwrite the below #define if you know your architecture endianess. ++ */ ++#if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || \ ++ defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || \ ++ defined(__PPC) || defined(PPC) || defined(__powerpc__) || \ ++ defined(__powerpc) || defined(powerpc) || \ ++ ((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))) ++#define LZ4_BIG_ENDIAN 1 ++#else ++ /* ++ * Little Endian assumed. PDP Endian and other very rare endian format ++ * are unsupported. ++ */ ++#endif ++ ++/* ++ * Compiler Options ++ */ ++ ++#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ ++/* "restrict" is a known keyword */ ++#else ++/* Disable restrict */ ++#ifndef restrict ++#define restrict /* Only if somebody already didn't take care of that.*/ ++#endif ++#endif ++ ++#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) ++ ++#define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) \ ++ | (((x) & 0xffu) << 8))) ++ ++#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) ++#define expect(expr, value) (__builtin_expect((expr), (value))) ++#else ++#define expect(expr, value) (expr) ++#endif ++ ++#define likely(expr) expect((expr) != 0, 1) ++#define unlikely(expr) expect((expr) != 0, 0) ++ ++/* Basic types */ ++#define BYTE grub_uint8_t ++#define U16 grub_uint16_t ++#define U32 grub_uint32_t ++#define S32 grub_int32_t ++#define U64 grub_uint64_t ++typedef grub_size_t size_t; ++ ++typedef struct _U16_S { ++ U16 v; ++} U16_S; ++typedef struct _U32_S { ++ U32 v; ++} U32_S; ++typedef struct _U64_S { ++ U64 v; ++} U64_S; ++ ++#define A64(x) (((U64_S *)(x))->v) ++#define A32(x) (((U32_S *)(x))->v) ++#define A16(x) (((U16_S *)(x))->v) ++ ++/* ++ * Constants ++ */ ++#define MINMATCH 4 ++ ++#define COPYLENGTH 8 ++#define LASTLITERALS 5 ++ ++#define ML_BITS 4 ++#define ML_MASK ((1U<<ML_BITS)-1) ++#define RUN_BITS (8-ML_BITS) ++#define RUN_MASK ((1U<<RUN_BITS)-1) ++ ++/* ++ * Architecture-specific macros ++ */ ++#if LZ4_ARCH64 ++#define STEPSIZE 8 ++#define UARCH U64 ++#define AARCH A64 ++#define LZ4_COPYSTEP(s, d) A64(d) = A64(s); d += 8; s += 8; ++#define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d) ++#define LZ4_SECURECOPY(s, d, e) if (d < e) LZ4_WILDCOPY(s, d, e) ++#define HTYPE U32 ++#define INITBASE(base) const BYTE* const base = ip ++#else ++#define STEPSIZE 4 ++#define UARCH U32 ++#define AARCH A32 ++#define LZ4_COPYSTEP(s, d) A32(d) = A32(s); d += 4; s += 4; ++#define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d); LZ4_COPYSTEP(s, d); ++#define LZ4_SECURECOPY LZ4_WILDCOPY ++#define HTYPE const BYTE* ++#define INITBASE(base) const int base = 0 ++#endif ++ ++#if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE)) ++#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \ ++ { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; } ++#define LZ4_WRITE_LITTLEENDIAN_16(p, i) \ ++ { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p += 2; } ++#else ++#define LZ4_READ_LITTLEENDIAN_16(d, s, p) { d = (s) - A16(p); } ++#define LZ4_WRITE_LITTLEENDIAN_16(p, v) { A16(p) = v; p += 2; } ++#endif ++ ++/* Macros */ ++#define LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e); ++ ++/* Decompression functions */ ++grub_err_t ++lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len); ++ ++grub_err_t ++lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len) ++{ ++ const BYTE *src = s_start; ++ U32 bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | ++ src[3]; ++ ++ /* invalid compressed buffer size encoded at start */ ++ if (bufsiz + 4 > s_len) ++ return grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."); ++ ++ /* ++ * Returns 0 on success (decompression function returned non-negative) ++ * and appropriate error on failure (decompression function returned negative). ++ */ ++ return (LZ4_uncompress_unknownOutputSize((char*)s_start + 4, d_start, bufsiz, ++ d_len) < 0)?grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."):0; ++} ++ ++static int ++LZ4_uncompress_unknownOutputSize(const char *source, ++ char *dest, int isize, int maxOutputSize) ++{ ++ /* Local Variables */ ++ const BYTE *restrict ip = (const BYTE *) source; ++ const BYTE *const iend = ip + isize; ++ const BYTE *restrict ref; ++ ++ BYTE *restrict op = (BYTE *) dest; ++ BYTE *const oend = op + maxOutputSize; ++ BYTE *cpy; ++ ++ size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 }; ++ ++ /* Main Loop */ ++ while (ip < iend) { ++ BYTE token; ++ int length; ++ ++ /* get runlength */ ++ token = *ip++; ++ if ((length = (token >> ML_BITS)) == RUN_MASK) { ++ int s = 255; ++ while ((ip < iend) && (s == 255)) { ++ s = *ip++; ++ length += s; ++ } ++ } ++ /* copy literals */ ++ cpy = op + length; ++ if ((cpy > oend - COPYLENGTH) || ++ (ip + length > iend - COPYLENGTH)) { ++ if (cpy > oend) ++ /* ++ * Error: request to write beyond destination ++ * buffer. ++ */ ++ goto _output_error; ++ if (ip + length > iend) ++ /* ++ * Error : request to read beyond source ++ * buffer. ++ */ ++ goto _output_error; ++ grub_memcpy(op, ip, length); ++ op += length; ++ ip += length; ++ if (ip < iend) ++ /* Error : LZ4 format violation */ ++ goto _output_error; ++ /* Necessarily EOF, due to parsing restrictions. */ ++ break; ++ } ++ LZ4_WILDCOPY(ip, op, cpy); ++ ip -= (op - cpy); ++ op = cpy; ++ ++ /* get offset */ ++ LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); ++ ip += 2; ++ if (ref < (BYTE * const) dest) ++ /* ++ * Error: offset creates reference outside of ++ * destination buffer. ++ */ ++ goto _output_error; ++ ++ /* get matchlength */ ++ if ((length = (token & ML_MASK)) == ML_MASK) { ++ while (ip < iend) { ++ int s = *ip++; ++ length += s; ++ if (s == 255) ++ continue; ++ break; ++ } ++ } ++ /* copy repeated sequence */ ++ if unlikely(op - ref < STEPSIZE) { ++#if LZ4_ARCH64 ++ size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 }; ++ size_t dec2 = dec2table[op - ref]; ++#else ++ const int dec2 = 0; ++#endif ++ *op++ = *ref++; ++ *op++ = *ref++; ++ *op++ = *ref++; ++ *op++ = *ref++; ++ ref -= dec[op - ref]; ++ A32(op) = A32(ref); ++ op += STEPSIZE - 4; ++ ref -= dec2; ++ } else { ++ LZ4_COPYSTEP(ref, op); ++ } ++ cpy = op + length - (STEPSIZE - 4); ++ if (cpy > oend - COPYLENGTH) { ++ if (cpy > oend) ++ /* ++ * Error: request to write outside of ++ * destination buffer. ++ */ ++ goto _output_error; ++ LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); ++ while (op < cpy) ++ *op++ = *ref++; ++ op = cpy; ++ if (op == oend) ++ /* ++ * Check EOF (should never happen, since last ++ * 5 bytes are supposed to be literals). ++ */ ++ break; ++ continue; ++ } ++ LZ4_SECURECOPY(ref, op, cpy); ++ op = cpy; /* correction */ ++ } ++ ++ /* end of decoding */ ++ return (int)(((char *)op) - dest); ++ ++ /* write overflow error detected */ ++ _output_error: ++ return (int)(-(((char *)ip) - source)); ++} +diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c +index fdb587a..c96bf21 100644 +--- a/grub-core/fs/zfs/zfsinfo.c ++++ b/grub-core/fs/zfs/zfsinfo.c +@@ -132,21 +132,31 @@ print_vdev_info (char *nvlist, int tab) + grub_free (path); + return GRUB_ERR_NONE; + } ++ char is_mirror=(grub_strcmp(type,VDEV_TYPE_MIRROR) == 0); ++ char is_raidz=(grub_strcmp(type,VDEV_TYPE_RAIDZ) == 0); + +- if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0) ++ if (is_mirror || is_raidz) + { + int nelm, i; + + nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm + (nvlist, ZPOOL_CONFIG_CHILDREN); + ++ if(is_mirror){ ++ grub_puts_ (N_("This VDEV is a mirror")); ++ } ++ else if(is_raidz){ ++ grub_uint64_t parity; ++ grub_zfs_nvlist_lookup_uint64(nvlist,"nparity",&parity); ++ grub_printf_ (N_("This VDEV is a RAIDZ%llu\n"),(unsigned long long)parity); ++ } + print_tabs (tab); + if (nelm <= 0) + { +- grub_puts_ (N_("Incorrect mirror")); ++ grub_puts_ (N_("Incorrect VDEV")); + return GRUB_ERR_NONE; + } +- grub_printf_ (N_("Mirror with %d children\n"), nelm); ++ grub_printf_ (N_("VDEV with %d children\n"), nelm); + print_state (nvlist, tab); + for (i = 0; i < nelm; i++) + { +@@ -162,14 +172,14 @@ print_vdev_info (char *nvlist, int tab) + total element number. And the number itself is fine, + only the element isn't. + */ +- grub_printf_ (N_("Mirror element number %d isn't correct\n"), i); ++ grub_printf_ (N_("VDEV element number %d isn't correct\n"), i); + continue; + } + + /* TRANSLATORS: it's the element carying the number %d, not + total element number. This is used in enumeration + "Element number 1", "Element number 2", ... */ +- grub_printf_ (N_("Mirror element number %d:\n"), i); ++ grub_printf_ (N_("VDEV element number %d:\n"), i); + print_vdev_info (child, tab + 1); + + grub_free (child); +diff --git a/include/grub/zfs/dmu.h b/include/grub/zfs/dmu.h +index 8fc6dc5..4ad616c 100644 +--- a/include/grub/zfs/dmu.h ++++ b/include/grub/zfs/dmu.h +@@ -22,6 +22,39 @@ + + #ifndef _SYS_DMU_H + #define _SYS_DMU_H ++#define B_FALSE 0 ++#define B_TRUE 1 ++ ++#define DMU_OT_NEWTYPE 0x80 ++#define DMU_OT_METADATA 0x40 ++#define DMU_OT_BYTESWAP_MASK 0x3f ++ ++#define DMU_OT(byteswap, metadata) \ ++ (DMU_OT_NEWTYPE | \ ++ ((metadata) ? DMU_OT_METADATA : 0) | \ ++ ((byteswap) & DMU_OT_BYTESWAP_MASK)) ++ ++#define DMU_OT_IS_VALID(ot) (((ot) & DMU_OT_NEWTYPE) ? \ ++ ((ot) & DMU_OT_BYTESWAP_MASK) < DMU_BSWAP_NUMFUNCS : \ ++ (ot) < DMU_OT_NUMTYPES) ++ ++#define DMU_OT_IS_METADATA(ot) (((ot) & DMU_OT_NEWTYPE) ? \ ++ ((ot) & DMU_OT_METADATA) : \ ++ dmu_ot[(ot)].ot_metadata) ++ ++typedef enum dmu_object_byteswap { ++ DMU_BSWAP_UINT8, ++ DMU_BSWAP_UINT16, ++ DMU_BSWAP_UINT32, ++ DMU_BSWAP_UINT64, ++ DMU_BSWAP_ZAP, ++ DMU_BSWAP_DNODE, ++ DMU_BSWAP_OBJSET, ++ DMU_BSWAP_ZNODE, ++ DMU_BSWAP_OLDACL, ++ DMU_BSWAP_ACL, ++ DMU_BSWAP_NUMFUNCS ++} dmu_object_byteswap_t; + + /* + * This file describes the interface that the DMU provides for its +@@ -89,7 +122,17 @@ typedef enum dmu_object_type { + DMU_OT_SA_ATTR_REGISTRATION, /* ZAP */ + DMU_OT_SA_ATTR_LAYOUTS, /* ZAP */ + DMU_OT_DSL_KEYCHAIN = 54, +- DMU_OT_NUMTYPES ++ DMU_OT_NUMTYPES, ++ DMU_OTN_UINT8_DATA = DMU_OT(DMU_BSWAP_UINT8, B_FALSE), ++ DMU_OTN_UINT8_METADATA = DMU_OT(DMU_BSWAP_UINT8, B_TRUE), ++ DMU_OTN_UINT16_DATA = DMU_OT(DMU_BSWAP_UINT16, B_FALSE), ++ DMU_OTN_UINT16_METADATA = DMU_OT(DMU_BSWAP_UINT16, B_TRUE), ++ DMU_OTN_UINT32_DATA = DMU_OT(DMU_BSWAP_UINT32, B_FALSE), ++ DMU_OTN_UINT32_METADATA = DMU_OT(DMU_BSWAP_UINT32, B_TRUE), ++ DMU_OTN_UINT64_DATA = DMU_OT(DMU_BSWAP_UINT64, B_FALSE), ++ DMU_OTN_UINT64_METADATA = DMU_OT(DMU_BSWAP_UINT64, B_TRUE), ++ DMU_OTN_ZAP_DATA = DMU_OT(DMU_BSWAP_ZAP, B_FALSE), ++ DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE), + } dmu_object_type_t; + + typedef enum dmu_objset_type { +@@ -116,5 +159,6 @@ typedef enum dmu_objset_type { + #define DMU_POOL_HISTORY "history" + #define DMU_POOL_PROPS "pool_props" + #define DMU_POOL_L2CACHE "l2cache" ++#define DMU_POOL_FEATURES_FOR_READ "features_for_read" + + #endif /* _SYS_DMU_H */ +diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h +index e326c8b..761ade7 100644 +--- a/include/grub/zfs/zfs.h ++++ b/include/grub/zfs/zfs.h +@@ -36,8 +36,13 @@ typedef enum grub_zfs_endian + /* + * On-disk version number. + */ +-#define SPA_VERSION 33ULL +- ++#define SPA_VERSION_INITIAL 1ULL ++#define SPA_VERSION_BEFORE_FEATURES 33ULL ++#define SPA_VERSION 5000ULL ++#define SPA_VERSION_FEATURES 5000ULL ++#define SPA_VERSION_IS_SUPPORTED(v) \ ++ (((v) >= SPA_VERSION_INITIAL && (v) <= SPA_VERSION_BEFORE_FEATURES) || \ ++ ((v) >= SPA_VERSION_FEATURES && (v) <= SPA_VERSION)) + /* + * The following are configuration names used in the nvlist describing a pool's + * configuration. +@@ -76,6 +81,7 @@ typedef enum grub_zfs_endian + #define ZPOOL_CONFIG_DDT_HISTOGRAM "ddt_histogram" + #define ZPOOL_CONFIG_DDT_OBJ_STATS "ddt_object_stats" + #define ZPOOL_CONFIG_DDT_STATS "ddt_stats" ++#define ZPOOL_CONFIG_FEATURES_FOR_READ "features_for_read" + /* + * The persistent vdev state is stored as separate values rather than a single + * 'vdev_state' entry. This is because a device can be in multiple states, such +diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h +index b1c46da..8fad2cc 100644 +--- a/include/grub/zfs/zio.h ++++ b/include/grub/zfs/zio.h +@@ -88,6 +88,7 @@ enum zio_compress { + ZIO_COMPRESS_GZIP8, + ZIO_COMPRESS_GZIP9, + ZIO_COMPRESS_ZLE, ++ ZIO_COMPRESS_LZ4, + ZIO_COMPRESS_FUNCTIONS + }; + +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 987b37a..c55d9e3 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -173,6 +173,7 @@ + ./grub-core/fs/zfs/zfs_fletcher.c + ./grub-core/fs/zfs/zfsinfo.c + ./grub-core/fs/zfs/zfs_lzjb.c ++./grub-core/fs/zfs/zfs_lz4.c + ./grub-core/fs/zfs/zfs_sha256.c + ./grub-core/gdb/cstub.c + ./grub-core/gdb/gdb.c diff --git a/sys-boot/grub/files/grub-2.00-zfs-feature-flag-support.patch b/sys-boot/grub/files/grub-2.00-zfs-feature-flag-support.patch new file mode 100644 index 00000000..998dc073 --- /dev/null +++ b/sys-boot/grub/files/grub-2.00-zfs-feature-flag-support.patch @@ -0,0 +1,1017 @@ +ZFS Feature Flag Support + +This is a monolithic version of the following commits: + +https://github.com/maxximino/grub2/commit/31a32560fd7948ae5ff5c63105d7c068de7890c8 +https://github.com/maxximino/grub2/commit/595d76e8ca0690a963f5533689de8db54ef07e75 +https://github.com/maxximino/grub2/commit/58344034e40218b20500fa2936eb4d7d019e1e88 +https://github.com/maxximino/grub2/commit/f98cb078abab2c14bb0766b5a0ceb055683dab81 +https://github.com/maxximino/grub2/commit/f12806f43a969a654dee7bb89b2e8fd5c42f0e2e + +A minor change was made to account for d8a0feb6 from upstream. This change +prevents a compile time failure that is caused by a change in the callback +interface used by mzap_interate(). + +The initial feature flag support patches were written by Delphix while the LZ4 +support was written by Saso Kiselkov. The work porting this to GRUB2 was done +by Massimo Maggi, while the adaption to Gentoo's GRUB2 package was done by +Richard Yao. + +diff --git a/Makefile.util.def b/Makefile.util.def +index b80187c..1bf3038 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -95,6 +95,7 @@ library = { + common = grub-core/fs/zfs/zfs.c; + common = grub-core/fs/zfs/zfsinfo.c; + common = grub-core/fs/zfs/zfs_lzjb.c; ++ common = grub-core/fs/zfs/zfs_lz4.c; + common = grub-core/fs/zfs/zfs_sha256.c; + common = grub-core/fs/zfs/zfs_fletcher.c; + common = grub-core/lib/envblk.c; +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 39e77a4..1550b90 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1186,6 +1186,7 @@ module = { + name = zfs; + common = fs/zfs/zfs.c; + common = fs/zfs/zfs_lzjb.c; ++ common = fs/zfs/zfs_lz4.c; + common = fs/zfs/zfs_sha256.c; + common = fs/zfs/zfs_fletcher.c; + }; +diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c +index ba0554a..de31e6c 100644 +--- a/grub-core/fs/zfs/zfs.c ++++ b/grub-core/fs/zfs/zfs.c +@@ -2,6 +2,7 @@ + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011 Free Software Foundation, Inc. + * Copyright 2010 Sun Microsystems, Inc. ++ * Copyright (c) 2012 by Delphix. All rights reserved. + * + * GRUB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -153,11 +154,13 @@ ZAP_LEAF_ENTRY(zap_leaf_phys_t *l, int bs, int idx) + + + /* +- * Decompression Entry - lzjb ++ * Decompression Entry - lzjb & lz4 + */ + + extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t); + ++extern grub_err_t lz4_decompress (void *, void *, grub_size_t, grub_size_t); ++ + typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start, + grub_size_t s_len, grub_size_t d_len); + typedef struct decomp_entry +@@ -263,6 +266,19 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key + grub_size_t keysize, + grub_uint64_t salt, + grub_uint64_t algo) = NULL; ++/* ++ * List of pool features that the grub implementation of ZFS supports for ++ * read. Note that features that are only required for write do not need ++ * to be listed here since grub opens pools in read-only mode. ++ */ ++static const char *spa_feature_names[] = { ++ "org.illumos:lz4_compress",NULL ++}; ++ ++static int ++check_feature(const char *name, grub_uint64_t val); ++static int ++check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ); + + static grub_err_t + zlib_decompress (void *s, void *d, +@@ -322,6 +338,7 @@ static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { + {"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */ + {"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */ + {"zle", zle_decompress}, /* ZIO_COMPRESS_ZLE */ ++ {"lz4", lz4_decompress}, /* ZIO_COMPRESS_LZ4 */ + }; + + static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, +@@ -482,15 +499,11 @@ uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset, + + if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) + == UBERBLOCK_MAGIC +- && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) > 0 +- && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) +- <= SPA_VERSION) +- endian = GRUB_ZFS_LITTLE_ENDIAN; ++ && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN))) ++ endian = GRUB_ZFS_LITTLE_ENDIAN; + + if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_BIG_ENDIAN) == UBERBLOCK_MAGIC +- && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) > 0 +- && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) +- <= SPA_VERSION) ++ && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN))) + endian = GRUB_ZFS_BIG_ENDIAN; + + if (endian == GRUB_ZFS_UNKNOWN_ENDIAN) +@@ -764,6 +777,155 @@ fill_vdev_info (struct grub_zfs_data *data, + } + + /* ++ * For a given XDR packed nvlist, verify the first 4 bytes and move on. ++ * ++ * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : ++ * ++ * encoding method/host endian (4 bytes) ++ * nvl_version (4 bytes) ++ * nvl_nvflag (4 bytes) ++ * encoded nvpairs: ++ * encoded size of the nvpair (4 bytes) ++ * decoded size of the nvpair (4 bytes) ++ * name string size (4 bytes) ++ * name string data (sizeof(NV_ALIGN4(string)) ++ * data type (4 bytes) ++ * # of elements in the nvpair (4 bytes) ++ * data ++ * 2 zero's for the last nvpair ++ * (end of the entire list) (8 bytes) ++ * ++ */ ++ ++/* ++ * The nvlist_next_nvpair() function returns a handle to the next nvpair in the ++ * list following nvpair. If nvpair is NULL, the first pair is returned. If ++ * nvpair is the last pair in the nvlist, NULL is returned. ++ */ ++static const char * ++nvlist_next_nvpair(const char *nvl, const char *nvpair) ++{ ++ const char *nvp; ++ int encode_size; ++ int name_len; ++ if (nvl == NULL) ++ return (NULL); ++ ++ if (nvpair == NULL) { ++ /* skip over header, nvl_version and nvl_nvflag */ ++ nvpair = nvl + 4 * 3; ++ } else { ++ /* skip to the next nvpair */ ++ encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair)); ++ nvpair += encode_size; ++ } ++ /* 8 bytes of 0 marks the end of the list */ ++ if (*(grub_uint64_t*)nvpair == 0) ++ return (NULL); ++ /*consistency checks*/ ++ if (nvpair + 4 * 3 >= nvl + VDEV_PHYS_SIZE) ++ { ++ grub_dprintf ("zfs", "nvlist overflow\n"); ++ grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); ++ return (NULL); ++ } ++ encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair)); ++ ++ nvp = nvpair + 4*2; ++ name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); ++ nvp += 4; ++ ++ nvp = nvp + ((name_len + 3) & ~3); // align ++ if (nvp + 4 >= nvl + VDEV_PHYS_SIZE ++ || encode_size < 0 ++ || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE) ++ { ++ grub_dprintf ("zfs", "nvlist overflow\n"); ++ grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); ++ return (NULL); ++ } ++ /* end consistency checks */ ++ ++ return (nvpair); ++} ++/* ++ * This function returns 0 on success and 1 on failure. On success, a string ++ * containing the name of nvpair is saved in buf. ++ */ ++static int ++nvpair_name(const char *nvp, char **buf, int* buflen) ++{ ++ int len; ++ ++ /* skip over encode/decode size */ ++ nvp += 4 * 2; ++ ++ len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); ++ nvp=nvp+4; ++ ++ *buf=(char*)nvp; ++ *buflen=len; ++ ++ return (0); ++} ++/* ++ * This function retrieves the value of the nvpair in the form of enumerated ++ * type data_type_t. ++ */ ++static int ++nvpair_type(const char *nvp) ++{ ++ int name_len, type; ++ ++ /* skip over encode/decode size */ ++ nvp += 4 * 2; ++ ++ /* skip over name_len */ ++ name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); ++ nvp += 4; ++ ++ /* skip over name */ ++ nvp = nvp + ((name_len + 3) & ~3); /* align */ ++ ++ type = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); ++ ++ return (type); ++} ++static int ++nvpair_value(const char *nvp,char **val, ++ grub_size_t *size_out, grub_size_t *nelm_out) ++{ ++ int name_len,nelm,encode_size; ++ ++ /* skip over encode/decode size */ ++ encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvp)); ++ nvp += 8; ++ ++ /* skip over name_len */ ++ name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); ++ nvp += 4; ++ ++ /* skip over name */ ++ nvp = nvp + ((name_len + 3) & ~3); /* align */ ++ ++ /* skip over type */ ++ nvp += 4; ++ nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); ++ nvp +=4; ++ if (nelm < 1) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "empty nvpair"); ++ return 0; ++ } ++ *val = (char *) nvp; ++ *size_out = encode_size; ++ if (nelm_out) ++ *nelm_out = nelm; ++ ++ return 1; ++} ++ ++/* + * Check the disk label information and retrieve needed vdev name-value pairs. + * + */ +@@ -773,7 +935,7 @@ check_pool_label (struct grub_zfs_data *data, + int *inserted) + { + grub_uint64_t pool_state, txg = 0; +- char *nvlist; ++ char *nvlist,*features; + #if 0 + char *nv; + #endif +@@ -837,13 +999,13 @@ check_pool_label (struct grub_zfs_data *data, + } + grub_dprintf ("zfs", "check 8 passed\n"); + +- if (version > SPA_VERSION) ++ if (!SPA_VERSION_IS_SUPPORTED(version)) + { + grub_free (nvlist); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "too new version %llu > %llu", + (unsigned long long) version, +- (unsigned long long) SPA_VERSION); ++ (unsigned long long) SPA_VERSION_BEFORE_FEATURES); + } + grub_dprintf ("zfs", "check 9 passed\n"); + +@@ -893,7 +1055,30 @@ check_pool_label (struct grub_zfs_data *data, + grub_free (nv); + } + grub_dprintf ("zfs", "check 10 passed\n"); +- ++ if ((features=grub_zfs_nvlist_lookup_nvlist(nvlist, ZPOOL_CONFIG_FEATURES_FOR_READ))) ++ { ++ const char *nvp=NULL; ++ char *name = grub_zalloc(51); ++ char *nameptr; ++ int namelen; ++ while ((nvp = nvlist_next_nvpair(features, nvp)) != NULL) ++ { ++ nvpair_name(nvp, &nameptr,&namelen); ++ if(namelen > 50){namelen=50;} ++ grub_strncpy(name,nameptr,namelen); ++ name[namelen]=0; ++ grub_dprintf("zfs","namelen=%u str=%s\n",namelen,name); ++ if (check_feature(name,1) != 0) ++ { ++ grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name); ++ err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name); ++ grub_free(name); ++ return err; ++ } ++ } ++ grub_free(name); ++ } ++ grub_dprintf ("zfs", "check 12 passed (feature flags)\n"); + grub_free (nvlist); + + return GRUB_ERR_NONE; +@@ -3034,34 +3219,14 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + return err; + } + +-/* +- * For a given XDR packed nvlist, verify the first 4 bytes and move on. +- * +- * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : +- * +- * encoding method/host endian (4 bytes) +- * nvl_version (4 bytes) +- * nvl_nvflag (4 bytes) +- * encoded nvpairs: +- * encoded size of the nvpair (4 bytes) +- * decoded size of the nvpair (4 bytes) +- * name string size (4 bytes) +- * name string data (sizeof(NV_ALIGN4(string)) +- * data type (4 bytes) +- * # of elements in the nvpair (4 bytes) +- * data +- * 2 zero's for the last nvpair +- * (end of the entire list) (8 bytes) +- * +- */ +- + static int + nvlist_find_value (const char *nvlist_in, const char *name, + int valtype, char **val, + grub_size_t *size_out, grub_size_t *nelm_out) + { +- int name_len, type, encode_size; +- const char *nvpair, *nvp_name, *nvlist = nvlist_in; ++ int name_len, type ; ++ const char *nvpair=NULL,*nvlist=nvlist_in; ++ char *nvp_name; + + /* Verify if the 1st and 2nd byte in the nvlist are valid. */ + /* NOTE: independently of what endianness header announces all +@@ -3074,62 +3239,18 @@ nvlist_find_value (const char *nvlist_in, const char *name, + return 0; + } + +- /* skip the header, nvl_version, and nvl_nvflag */ +- nvlist = nvlist + 4 * 3; + /* + * Loop thru the nvpair list + * The XDR representation of an integer is in big-endian byte order. + */ +- while ((encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (nvlist)))) ++ while ((nvpair=nvlist_next_nvpair(nvlist,nvpair))) + { +- int nelm; +- +- if (nvlist + 4 * 4 >= nvlist_in + VDEV_PHYS_SIZE) +- { +- grub_dprintf ("zfs", "nvlist overflow\n"); +- grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); +- return 0; +- } +- +- nvpair = nvlist + 4 * 2; /* skip the encode/decode size */ +- +- name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); +- nvpair += 4; +- +- nvp_name = nvpair; +- nvpair = nvpair + ((name_len + 3) & ~3); /* align */ +- +- if (nvpair + 8 >= nvlist_in + VDEV_PHYS_SIZE +- || encode_size < 0 +- || nvpair + 8 + encode_size > nvlist_in + VDEV_PHYS_SIZE) ++ nvpair_name(nvpair,&nvp_name,&name_len); ++ type = nvpair_type(nvpair); ++ if ((grub_strncmp (nvp_name, name, grub_strlen(name)) == 0) && type == valtype) + { +- grub_dprintf ("zfs", "nvlist overflow\n"); +- grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); +- return 0; ++ return nvpair_value(nvpair,val,size_out,nelm_out); + } +- +- type = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); +- nvpair += 4; +- +- nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); +- if (nelm < 1) +- { +- grub_error (GRUB_ERR_BAD_FS, "empty nvpair"); +- return 0; +- } +- +- nvpair += 4; +- +- if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype) +- { +- *val = (char *) nvpair; +- *size_out = encode_size; +- if (nelm_out) +- *nelm_out = nelm; +- return 1; +- } +- +- nvlist += encode_size; /* goto the next nvpair */ + } + return 0; + } +@@ -3386,6 +3507,10 @@ zfs_mount (grub_device_t dev) + return NULL; + } + ++ if (ub->ub_version >= SPA_VERSION_FEATURES && ++ check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian, data) != 0) ++ return NULL; ++ + /* Got the MOS. Save it at the memory addr MOS. */ + grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode, + DNODE_SIZE); +@@ -3910,6 +4035,64 @@ grub_zfs_dir (grub_device_t device, const char *path, + return grub_errno; + } + ++static int ++check_feature(const char *name, grub_uint64_t val) ++{ ++ int i; ++ if(val ==0) return 0; ++ if(*name==0) return 0; ++ for (i = 0; spa_feature_names[i] != NULL; i++) ++ { ++ if (grub_strcmp(name, spa_feature_names[i]) == 0) ++ return 0; ++ } ++ grub_printf("missing feature for read '%s'\n",name); ++ return 1; ++} ++ ++/* ++ * Checks whether the MOS features that are active are supported by this ++ * (GRUB's) implementation of ZFS. ++ * ++ * Return: ++ * 0: Success. ++ * errnum: Failure. ++ */ ++ ++static int ++check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ) ++{ ++ grub_uint64_t objnum; ++ grub_uint8_t errnum = 0; ++ dnode_end_t dn,mosmdn; ++ mzap_phys_t* mzp; ++ grub_zfs_endian_t endianzap; ++ int size; ++ grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t)); ++ mosmdn.endian=endian; ++ if ((errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT, ++ DMU_OT_OBJECT_DIRECTORY, &dn,data)) != 0) ++ return (errnum); ++ ++ /* ++ * Find the object number for 'features_for_read' and retrieve its ++ * corresponding dnode. Note that we don't check features_for_write ++ * because GRUB is not opening the pool for write. ++ */ ++ if ((errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0)) != 0) ++ return (errnum); ++ ++ if ((errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data)) != 0) ++ return (errnum); ++ ++ if ((errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data)) != 0) ++ return (errnum); ++ ++ size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT; ++ return (mzap_iterate(mzp,endianzap, size, check_feature)); ++} ++ ++ + #ifdef GRUB_UTIL + static grub_err_t + grub_zfs_embed (grub_device_t device __attribute__ ((unused)), +diff --git a/grub-core/fs/zfs/zfs_lz4.c b/grub-core/fs/zfs/zfs_lz4.c +new file mode 100644 +index 0000000..f199434 +--- /dev/null ++++ b/grub-core/fs/zfs/zfs_lz4.c +@@ -0,0 +1,321 @@ ++/* ++ * LZ4 - Fast LZ compression algorithm ++ * Header File ++ * Copyright (C) 2011-2013, Yann Collet. ++ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are ++ * met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above ++ * copyright notice, this list of conditions and the following disclaimer ++ * in the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * You can contact the author at : ++ * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html ++ * - LZ4 source repository : http://code.google.com/p/lz4/ ++ */ ++ ++#include <grub/err.h> ++#include <grub/mm.h> ++#include <grub/misc.h> ++#include <grub/types.h> ++ ++static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, ++ int isize, int maxOutputSize); ++ ++/* ++ * CPU Feature Detection ++ */ ++ ++/* 32 or 64 bits ? */ ++#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || \ ++ defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || \ ++ defined(__LP64__) || defined(_LP64)) ++#define LZ4_ARCH64 1 ++#else ++#define LZ4_ARCH64 0 ++#endif ++ ++/* ++ * Little Endian or Big Endian? ++ * Note: overwrite the below #define if you know your architecture endianess. ++ */ ++#if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || \ ++ defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || \ ++ defined(__PPC) || defined(PPC) || defined(__powerpc__) || \ ++ defined(__powerpc) || defined(powerpc) || \ ++ ((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))) ++#define LZ4_BIG_ENDIAN 1 ++#else ++ /* ++ * Little Endian assumed. PDP Endian and other very rare endian format ++ * are unsupported. ++ */ ++#endif ++ ++/* ++ * Compiler Options ++ */ ++ ++#if __STDC_VERSION__ >= 199901L /* C99 */ ++/* "restrict" is a known keyword */ ++#else ++/* Disable restrict */ ++#ifndef restrict ++#define restrict /* Only if somebody already didn't take care of that.*/ ++#endif ++#endif ++ ++#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) ++ ++#define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) \ ++ | (((x) & 0xffu) << 8))) ++ ++#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) ++#define expect(expr, value) (__builtin_expect((expr), (value))) ++#else ++#define expect(expr, value) (expr) ++#endif ++ ++#define likely(expr) expect((expr) != 0, 1) ++#define unlikely(expr) expect((expr) != 0, 0) ++ ++/* Basic types */ ++#define BYTE grub_uint8_t ++#define U16 grub_uint16_t ++#define U32 grub_uint32_t ++#define S32 grub_int32_t ++#define U64 grub_uint64_t ++typedef grub_size_t size_t; ++ ++typedef struct _U16_S { ++ U16 v; ++} U16_S; ++typedef struct _U32_S { ++ U32 v; ++} U32_S; ++typedef struct _U64_S { ++ U64 v; ++} U64_S; ++ ++#define A64(x) (((U64_S *)(x))->v) ++#define A32(x) (((U32_S *)(x))->v) ++#define A16(x) (((U16_S *)(x))->v) ++ ++/* ++ * Constants ++ */ ++#define MINMATCH 4 ++ ++#define COPYLENGTH 8 ++#define LASTLITERALS 5 ++ ++#define ML_BITS 4 ++#define ML_MASK ((1U<<ML_BITS)-1) ++#define RUN_BITS (8-ML_BITS) ++#define RUN_MASK ((1U<<RUN_BITS)-1) ++ ++/* ++ * Architecture-specific macros ++ */ ++#if LZ4_ARCH64 ++#define STEPSIZE 8 ++#define UARCH U64 ++#define AARCH A64 ++#define LZ4_COPYSTEP(s, d) A64(d) = A64(s); d += 8; s += 8; ++#define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d) ++#define LZ4_SECURECOPY(s, d, e) if (d < e) LZ4_WILDCOPY(s, d, e) ++#define HTYPE U32 ++#define INITBASE(base) const BYTE* const base = ip ++#else ++#define STEPSIZE 4 ++#define UARCH U32 ++#define AARCH A32 ++#define LZ4_COPYSTEP(s, d) A32(d) = A32(s); d += 4; s += 4; ++#define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d); LZ4_COPYSTEP(s, d); ++#define LZ4_SECURECOPY LZ4_WILDCOPY ++#define HTYPE const BYTE* ++#define INITBASE(base) const int base = 0 ++#endif ++ ++#if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE)) ++#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \ ++ { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; } ++#define LZ4_WRITE_LITTLEENDIAN_16(p, i) \ ++ { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p += 2; } ++#else ++#define LZ4_READ_LITTLEENDIAN_16(d, s, p) { d = (s) - A16(p); } ++#define LZ4_WRITE_LITTLEENDIAN_16(p, v) { A16(p) = v; p += 2; } ++#endif ++ ++/* Macros */ ++#define LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e); ++ ++/* Decompression functions */ ++grub_err_t ++lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len); ++ ++grub_err_t ++lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len) ++{ ++ const BYTE *src = s_start; ++ U32 bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | ++ src[3]; ++ ++ /* invalid compressed buffer size encoded at start */ ++ if (bufsiz + 4 > s_len) ++ return grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."); ++ ++ /* ++ * Returns 0 on success (decompression function returned non-negative) ++ * and appropriate error on failure (decompression function returned negative). ++ */ ++ return (LZ4_uncompress_unknownOutputSize((char*)s_start + 4, d_start, bufsiz, ++ d_len) < 0)?grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."):0; ++} ++ ++static int ++LZ4_uncompress_unknownOutputSize(const char *source, ++ char *dest, int isize, int maxOutputSize) ++{ ++ /* Local Variables */ ++ const BYTE *restrict ip = (const BYTE *) source; ++ const BYTE *const iend = ip + isize; ++ const BYTE *restrict ref; ++ ++ BYTE *restrict op = (BYTE *) dest; ++ BYTE *const oend = op + maxOutputSize; ++ BYTE *cpy; ++ ++ size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 }; ++ ++ /* Main Loop */ ++ while (ip < iend) { ++ BYTE token; ++ int length; ++ ++ /* get runlength */ ++ token = *ip++; ++ if ((length = (token >> ML_BITS)) == RUN_MASK) { ++ int s = 255; ++ while ((ip < iend) && (s == 255)) { ++ s = *ip++; ++ length += s; ++ } ++ } ++ /* copy literals */ ++ cpy = op + length; ++ if ((cpy > oend - COPYLENGTH) || ++ (ip + length > iend - COPYLENGTH)) { ++ if (cpy > oend) ++ /* ++ * Error: request to write beyond destination ++ * buffer. ++ */ ++ goto _output_error; ++ if (ip + length > iend) ++ /* ++ * Error : request to read beyond source ++ * buffer. ++ */ ++ goto _output_error; ++ grub_memcpy(op, ip, length); ++ op += length; ++ ip += length; ++ if (ip < iend) ++ /* Error : LZ4 format violation */ ++ goto _output_error; ++ /* Necessarily EOF, due to parsing restrictions. */ ++ break; ++ } ++ LZ4_WILDCOPY(ip, op, cpy); ++ ip -= (op - cpy); ++ op = cpy; ++ ++ /* get offset */ ++ LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); ++ ip += 2; ++ if (ref < (BYTE * const) dest) ++ /* ++ * Error: offset creates reference outside of ++ * destination buffer. ++ */ ++ goto _output_error; ++ ++ /* get matchlength */ ++ if ((length = (token & ML_MASK)) == ML_MASK) { ++ while (ip < iend) { ++ int s = *ip++; ++ length += s; ++ if (s == 255) ++ continue; ++ break; ++ } ++ } ++ /* copy repeated sequence */ ++ if unlikely(op - ref < STEPSIZE) { ++#if LZ4_ARCH64 ++ size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 }; ++ size_t dec2 = dec2table[op - ref]; ++#else ++ const int dec2 = 0; ++#endif ++ *op++ = *ref++; ++ *op++ = *ref++; ++ *op++ = *ref++; ++ *op++ = *ref++; ++ ref -= dec[op - ref]; ++ A32(op) = A32(ref); ++ op += STEPSIZE - 4; ++ ref -= dec2; ++ } else { ++ LZ4_COPYSTEP(ref, op); ++ } ++ cpy = op + length - (STEPSIZE - 4); ++ if (cpy > oend - COPYLENGTH) { ++ if (cpy > oend) ++ /* ++ * Error: request to write outside of ++ * destination buffer. ++ */ ++ goto _output_error; ++ LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); ++ while (op < cpy) ++ *op++ = *ref++; ++ op = cpy; ++ if (op == oend) ++ /* ++ * Check EOF (should never happen, since last ++ * 5 bytes are supposed to be literals). ++ */ ++ break; ++ continue; ++ } ++ LZ4_SECURECOPY(ref, op, cpy); ++ op = cpy; /* correction */ ++ } ++ ++ /* end of decoding */ ++ return (int)(((char *)op) - dest); ++ ++ /* write overflow error detected */ ++ _output_error: ++ return (int)(-(((char *)ip) - source)); ++} +diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c +index fdb587a..c96bf21 100644 +--- a/grub-core/fs/zfs/zfsinfo.c ++++ b/grub-core/fs/zfs/zfsinfo.c +@@ -132,21 +132,31 @@ print_vdev_info (char *nvlist, int tab) + grub_free (path); + return GRUB_ERR_NONE; + } ++ char is_mirror=(grub_strcmp(type,VDEV_TYPE_MIRROR) == 0); ++ char is_raidz=(grub_strcmp(type,VDEV_TYPE_RAIDZ) == 0); + +- if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0) ++ if (is_mirror || is_raidz) + { + int nelm, i; + + nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm + (nvlist, ZPOOL_CONFIG_CHILDREN); + ++ if(is_mirror){ ++ grub_puts_ (N_("This VDEV is a mirror")); ++ } ++ else if(is_raidz){ ++ grub_uint64_t parity; ++ grub_zfs_nvlist_lookup_uint64(nvlist,"nparity",&parity); ++ grub_printf_ (N_("This VDEV is a RAIDZ%llu\n"),(unsigned long long)parity); ++ } + print_tabs (tab); + if (nelm <= 0) + { +- grub_puts_ (N_("Incorrect mirror")); ++ grub_puts_ (N_("Incorrect VDEV")); + return GRUB_ERR_NONE; + } +- grub_printf_ (N_("Mirror with %d children\n"), nelm); ++ grub_printf_ (N_("VDEV with %d children\n"), nelm); + print_state (nvlist, tab); + for (i = 0; i < nelm; i++) + { +@@ -162,14 +172,14 @@ print_vdev_info (char *nvlist, int tab) + total element number. And the number itself is fine, + only the element isn't. + */ +- grub_printf_ (N_("Mirror element number %d isn't correct\n"), i); ++ grub_printf_ (N_("VDEV element number %d isn't correct\n"), i); + continue; + } + + /* TRANSLATORS: it's the element carying the number %d, not + total element number. This is used in enumeration + "Element number 1", "Element number 2", ... */ +- grub_printf_ (N_("Mirror element number %d:\n"), i); ++ grub_printf_ (N_("VDEV element number %d:\n"), i); + print_vdev_info (child, tab + 1); + + grub_free (child); +diff --git a/include/grub/zfs/dmu.h b/include/grub/zfs/dmu.h +index 8fc6dc5..4ad616c 100644 +--- a/include/grub/zfs/dmu.h ++++ b/include/grub/zfs/dmu.h +@@ -22,6 +22,39 @@ + + #ifndef _SYS_DMU_H + #define _SYS_DMU_H ++#define B_FALSE 0 ++#define B_TRUE 1 ++ ++#define DMU_OT_NEWTYPE 0x80 ++#define DMU_OT_METADATA 0x40 ++#define DMU_OT_BYTESWAP_MASK 0x3f ++ ++#define DMU_OT(byteswap, metadata) \ ++ (DMU_OT_NEWTYPE | \ ++ ((metadata) ? DMU_OT_METADATA : 0) | \ ++ ((byteswap) & DMU_OT_BYTESWAP_MASK)) ++ ++#define DMU_OT_IS_VALID(ot) (((ot) & DMU_OT_NEWTYPE) ? \ ++ ((ot) & DMU_OT_BYTESWAP_MASK) < DMU_BSWAP_NUMFUNCS : \ ++ (ot) < DMU_OT_NUMTYPES) ++ ++#define DMU_OT_IS_METADATA(ot) (((ot) & DMU_OT_NEWTYPE) ? \ ++ ((ot) & DMU_OT_METADATA) : \ ++ dmu_ot[(ot)].ot_metadata) ++ ++typedef enum dmu_object_byteswap { ++ DMU_BSWAP_UINT8, ++ DMU_BSWAP_UINT16, ++ DMU_BSWAP_UINT32, ++ DMU_BSWAP_UINT64, ++ DMU_BSWAP_ZAP, ++ DMU_BSWAP_DNODE, ++ DMU_BSWAP_OBJSET, ++ DMU_BSWAP_ZNODE, ++ DMU_BSWAP_OLDACL, ++ DMU_BSWAP_ACL, ++ DMU_BSWAP_NUMFUNCS ++} dmu_object_byteswap_t; + + /* + * This file describes the interface that the DMU provides for its +@@ -89,7 +122,17 @@ typedef enum dmu_object_type { + DMU_OT_SA_ATTR_REGISTRATION, /* ZAP */ + DMU_OT_SA_ATTR_LAYOUTS, /* ZAP */ + DMU_OT_DSL_KEYCHAIN = 54, +- DMU_OT_NUMTYPES ++ DMU_OT_NUMTYPES, ++ DMU_OTN_UINT8_DATA = DMU_OT(DMU_BSWAP_UINT8, B_FALSE), ++ DMU_OTN_UINT8_METADATA = DMU_OT(DMU_BSWAP_UINT8, B_TRUE), ++ DMU_OTN_UINT16_DATA = DMU_OT(DMU_BSWAP_UINT16, B_FALSE), ++ DMU_OTN_UINT16_METADATA = DMU_OT(DMU_BSWAP_UINT16, B_TRUE), ++ DMU_OTN_UINT32_DATA = DMU_OT(DMU_BSWAP_UINT32, B_FALSE), ++ DMU_OTN_UINT32_METADATA = DMU_OT(DMU_BSWAP_UINT32, B_TRUE), ++ DMU_OTN_UINT64_DATA = DMU_OT(DMU_BSWAP_UINT64, B_FALSE), ++ DMU_OTN_UINT64_METADATA = DMU_OT(DMU_BSWAP_UINT64, B_TRUE), ++ DMU_OTN_ZAP_DATA = DMU_OT(DMU_BSWAP_ZAP, B_FALSE), ++ DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE), + } dmu_object_type_t; + + typedef enum dmu_objset_type { +@@ -116,5 +159,6 @@ typedef enum dmu_objset_type { + #define DMU_POOL_HISTORY "history" + #define DMU_POOL_PROPS "pool_props" + #define DMU_POOL_L2CACHE "l2cache" ++#define DMU_POOL_FEATURES_FOR_READ "features_for_read" + + #endif /* _SYS_DMU_H */ +diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h +index e326c8b..761ade7 100644 +--- a/include/grub/zfs/zfs.h ++++ b/include/grub/zfs/zfs.h +@@ -36,8 +36,13 @@ typedef enum grub_zfs_endian + /* + * On-disk version number. + */ +-#define SPA_VERSION 33ULL +- ++#define SPA_VERSION_INITIAL 1ULL ++#define SPA_VERSION_BEFORE_FEATURES 33ULL ++#define SPA_VERSION 5000ULL ++#define SPA_VERSION_FEATURES 5000ULL ++#define SPA_VERSION_IS_SUPPORTED(v) \ ++ (((v) >= SPA_VERSION_INITIAL && (v) <= SPA_VERSION_BEFORE_FEATURES) || \ ++ ((v) >= SPA_VERSION_FEATURES && (v) <= SPA_VERSION)) + /* + * The following are configuration names used in the nvlist describing a pool's + * configuration. +@@ -76,6 +81,7 @@ typedef enum grub_zfs_endian + #define ZPOOL_CONFIG_DDT_HISTOGRAM "ddt_histogram" + #define ZPOOL_CONFIG_DDT_OBJ_STATS "ddt_object_stats" + #define ZPOOL_CONFIG_DDT_STATS "ddt_stats" ++#define ZPOOL_CONFIG_FEATURES_FOR_READ "features_for_read" + /* + * The persistent vdev state is stored as separate values rather than a single + * 'vdev_state' entry. This is because a device can be in multiple states, such +diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h +index b1c46da..8fad2cc 100644 +--- a/include/grub/zfs/zio.h ++++ b/include/grub/zfs/zio.h +@@ -88,6 +88,7 @@ enum zio_compress { + ZIO_COMPRESS_GZIP8, + ZIO_COMPRESS_GZIP9, + ZIO_COMPRESS_ZLE, ++ ZIO_COMPRESS_LZ4, + ZIO_COMPRESS_FUNCTIONS + }; + +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 987b37a..c55d9e3 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -173,6 +173,7 @@ + ./grub-core/fs/zfs/zfs_fletcher.c + ./grub-core/fs/zfs/zfsinfo.c + ./grub-core/fs/zfs/zfs_lzjb.c ++./grub-core/fs/zfs/zfs_lz4.c + ./grub-core/fs/zfs/zfs_sha256.c + ./grub-core/gdb/cstub.c + ./grub-core/gdb/gdb.c diff --git a/sys-boot/grub/files/grub.conf.gentoo b/sys-boot/grub/files/grub.conf.gentoo new file mode 100644 index 00000000..0027099e --- /dev/null +++ b/sys-boot/grub/files/grub.conf.gentoo @@ -0,0 +1,16 @@ +# This is a sample grub.conf for use with Genkernel, per the Gentoo handbook +# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=1&chap=10#doc_chap2 +# If you are not using Genkernel and you need help creating this file, you +# should consult the handbook. Alternatively, consult the grub.conf.sample that +# is included with the Grub documentation. + +default 0 +timeout 30 +#splashimage=(hd0,0)/boot/grub/splash.xpm.gz + +#title Gentoo Linux 2.6.24-r5 +#root (hd0,0) +#kernel /boot/kernel-genkernel-x86-2.6.24-gentoo-r5 root=/dev/ram0 real_root=/dev/sda3 +#initrd /boot/initramfs-genkernel-x86-2.6.24-gentoo-r5 + +# vim:ft=conf: diff --git a/sys-boot/grub/files/grub.default-2 b/sys-boot/grub/files/grub.default-2 new file mode 100644 index 00000000..60f27303 --- /dev/null +++ b/sys-boot/grub/files/grub.default-2 @@ -0,0 +1,57 @@ +# Copyright 1999-2012 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/sys-boot/grub/files/grub.default-2,v 1.2 2012/06/28 22:36:53 floppym Exp $ +# +# To populate all changes in this file you need to regenerate your +# grub configuration file afterwards: +# 'grub2-mkconfig -o /boot/grub2/grub.cfg' +# +# See the grub info page for documentation on possible variables and +# their associated values. + +GRUB_DEFAULT=saved +GRUB_DISTRIBUTOR="RogentOS" + +GRUB_DEFAULT=0 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_HIDDEN_TIMEOUT_QUIET=true +GRUB_TIMEOUT=3 + +GRUB_CMDLINE_LINUX_DEFAULT="" +GRUB_CMDLINE_LINUX="" + +# Uncomment to disable graphical terminal (grub-pc only) +#GRUB_TERMINAL=console + +# The resolution used on graphical terminal. +# Note that you can use only modes which your graphic card supports via VBE. +# You can see them in real GRUB with the command `vbeinfo'. +GRUB_GFXMODE=1024x768 + +# Path to theme spec txt file. +# The starfield is by default provided with use truetype. +# NOTE: when enabling custom theme, ensure you have required font/etc. +#GRUB_THEME="/boot/grub2/themes/starfield/theme.txt" + +# Background image used on graphical terminal. +# Can be in various bitmap formats. +GRUB_BACKGROUND="/boot/grub/default-splash.png" + +# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to kernel +#GRUB_DISABLE_LINUX_UUID=true + +# Uncomment to disable generation of recovery mode menu entries +#GRUB_DISABLE_RECOVERY=true + +# Boot menu option normal color +GRUB_COLOR_NORMAL="white/black" + +# Boot menu option "highlight" color +GRUB_COLOR_HIGHLIGHT="magenta/black" + +if [ -f "/etc/default/rogentos-grub" ]; then + # this file is placed by the RogentOS Installer and contains + # custom GRUB_CMDLINE_LINUX parameters created at install + # time. + . /etc/default/rogentos-grub +fi diff --git a/sys-boot/grub/files/grub2-default b/sys-boot/grub/files/grub2-default new file mode 100644 index 00000000..c93a6e8f --- /dev/null +++ b/sys-boot/grub/files/grub2-default @@ -0,0 +1,62 @@ +# /etc/default/grub +# If you change this file, run 'grub-mkconfig -o /boot/grub/grub.cfg' afterwards to update +# /boot/grub/grub.cfg. + +GRUB_DEFAULT=saved +GRUB_DISTRIBUTOR="RogentOS" +GRUB_HIDDEN_TIMEOUT=0 +GRUB_HIDDEN_TIMEOUT_QUIET=true +GRUB_TIMEOUT=5 + +# Add your extra parameters here below +# Dear user, put your boot flags here ;-) +GRUB_CMDLINE_LINUX_DEFAULT="" +# ATTENTION ATTENTION ATTENTION +# DO NOT EDIT THIS MANUALLY NOR SET IT TO EMPTY IF IT'S ALREADY FILLED WITH +# SOMETHING (DONE BY THE INSTALLER). REALLY, DON'T ! +GRUB_CMDLINE_LINUX="" +# ATTENTION ATTENTION ATTENTION + +# Uncomment to disable graphical terminal (grub-pc only) +# GRUB_TERMINAL=console + +# The resolution used on graphical terminal +# note that you can use only modes which your graphic card supports via VBE +# you can see them in real GRUB with the command `vbeinfo' +GRUB_GFXMODE=1024x768 + +# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux +#GRUB_DISABLE_LINUX_UUID=true + +# Uncomment to disable generation of recovery mode menu entrys +# GRUB_DISABLE_LINUX_RECOVERY="false" + +# Default wallpaper image path +GRUB_WALLPAPER="/boot/grub/default-splash.png" + +# Boot menu option normal color +GRUB_COLOR_NORMAL="white/black" + +# Boot menu option "highlight" color +GRUB_COLOR_HIGHLIGHT="magenta/black" + +if [ -f "/etc/default/rogentos-grub" ]; then + # this file is placed by the RogentOS Installer and contains + # custom GRUB_CMDLINE_LINUX parameters created at install + # time. + source /etc/default/rogentos-grub +fi + +# DO NOT REMOVE THIS IF YOUR GRUB_CMDLINE_LINUX IS EMPTY (BACKWARD COMPAT) +if [ -z "${GRUB_CMDLINE_LINUX}" ]; then + if [ ! -e "/proc/cmdline" ]; then + echo "ATTENTION ATTENTION ATTENTION" >&2 + echo "GRUB_CMDLINE_LINUX is not set inside /etc/default/grub" >&2 + echo " cannot generate a bootable configuration." >&2 + else + echo "ATTENTION ATTENTION ATTENTION" >&2 + echo "GRUB_CMDLINE_LINUX is not set inside /etc/default/grub" >&2 + echo " grub is going to use your /proc/cmdline content" >&2 + GRUB_CMDLINE_LINUX="`cat /proc/cmdline | sed -e 's#BOOT_IMAGE=.* ro ##g'`" + fi +fi diff --git a/sys-boot/grub/files/grub2-default-1.99 b/sys-boot/grub/files/grub2-default-1.99 new file mode 100644 index 00000000..acaabfd7 --- /dev/null +++ b/sys-boot/grub/files/grub2-default-1.99 @@ -0,0 +1,49 @@ +# /etc/default/grub +# If you change this file, run 'grub-mkconfig -o /boot/grub/grub.cfg' afterwards to update +# /boot/grub/grub.cfg. + +GRUB_DEFAULT=saved +GRUB_DISTRIBUTOR="RogentOS" +GRUB_HIDDEN_TIMEOUT=0 +GRUB_HIDDEN_TIMEOUT_QUIET=true +GRUB_TIMEOUT=5 +GRUB_DISABLE_LINUX_UUID=true + +# Add your extra parameters here below +# Dear user, put your boot flags here ;-) +GRUB_CMDLINE_LINUX_DEFAULT="" +# ATTENTION ATTENTION ATTENTION +# DO NOT EDIT THIS MANUALLY NOR SET IT TO EMPTY IF IT'S ALREADY FILLED WITH +# SOMETHING (DONE BY THE INSTALLER). REALLY, DON'T ! +GRUB_CMDLINE_LINUX="" +# ATTENTION ATTENTION ATTENTION + +# Uncomment to disable graphical terminal (grub-pc only) +# GRUB_TERMINAL=console + +# The resolution used on graphical terminal +# note that you can use only modes which your graphic card supports via VBE +# you can see them in real GRUB with the command `vbeinfo' +GRUB_GFXMODE=1024x768 + +# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux +#GRUB_DISABLE_LINUX_UUID=true + +# Uncomment to disable generation of recovery mode menu entrys +# GRUB_DISABLE_LINUX_RECOVERY="false" + +# Default wallpaper image path +GRUB_WALLPAPER="/boot/grub/default-splash.png" + +# Boot menu option normal color +GRUB_COLOR_NORMAL="white/black" + +# Boot menu option "highlight" color +GRUB_COLOR_HIGHLIGHT="magenta/black" + +if [ -f "/etc/default/rogentos-grub" ]; then + # this file is placed by the RogentOS Installer and contains + # custom GRUB_CMDLINE_LINUX parameters created at install + # time. + . /etc/default/rogentos-grub +fi diff --git a/sys-boot/grub/files/splash.xpm.gz b/sys-boot/grub/files/splash.xpm.gz Binary files differnew file mode 100644 index 00000000..f6836bda --- /dev/null +++ b/sys-boot/grub/files/splash.xpm.gz diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/01_uuids_and_lvm_dont_play_along_nicely.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/01_uuids_and_lvm_dont_play_along_nicely.diff new file mode 100644 index 00000000..c997b845 --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/01_uuids_and_lvm_dont_play_along_nicely.diff @@ -0,0 +1,14 @@ +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index c2da413..cbd9d6b 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -36,7 +36,8 @@ case ${GRUB_DEVICE} in + esac + + if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ +- || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then ++ || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \ ++ || [ "`grub-probe -t abstraction --device ${GRUB_DEVICE} | sed -e 's,.*\(lvm\).*,\1,'`" = "lvm" ] ; then + LINUX_ROOT_DEVICE=${GRUB_DEVICE} + else + LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/902_boot_blocklist_hack.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/902_boot_blocklist_hack.diff new file mode 100644 index 00000000..63caf45e --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/902_boot_blocklist_hack.diff @@ -0,0 +1,20 @@ +Index: util/i386/pc/grub-setup.c +=================================================================== +--- util/i386/pc/grub-setup.c (revision 1836) ++++ util/i386/pc/grub-setup.c (working copy) +@@ -383,6 +383,15 @@ + grub_disk_cache_invalidate_all (); + + file = grub_file_open (core_path_dev); ++ ++ if (grub_errno == GRUB_ERR_FILE_NOT_FOUND) ++ { ++ /* Clean the previous grub_errno */ ++ grub_errno = GRUB_ERR_NONE; ++ strcpy (core_path_dev, "/grub/core.img"); ++ file = grub_file_open (core_path_dev); ++ } ++ + if (file) + { + if (grub_file_size (file) != core_size) diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/904_disable_floppies.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/904_disable_floppies.diff new file mode 100644 index 00000000..66a41cdc --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/904_disable_floppies.diff @@ -0,0 +1,28 @@ + +Author: Robert Millan + +An ugly kludge. Should this be merged upstream? + +Index: util/hostdisk.c +=================================================================== +--- util/hostdisk.c (revision 1832) ++++ util/hostdisk.c (working copy) +@@ -544,6 +544,18 @@ + continue; + } + ++ if (! strncmp (p, "/dev/fd", sizeof ("/dev/fd") - 1)) ++ { ++ char *q = p + sizeof ("/dev/fd") - 1; ++ if (*q >= '0' && *q <= '9') ++ { ++ free (map[drive].drive); ++ map[drive].drive = NULL; ++ grub_util_info ("`%s' looks like a floppy drive, skipping", p); ++ continue; ++ } ++ } ++ + #ifdef __linux__ + /* On Linux, the devfs uses symbolic links horribly, and that + confuses the interface very much, so use realpath to expand diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/956_loopback_root.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/956_loopback_root.diff new file mode 100644 index 00000000..ce54872e --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/956_loopback_root.diff @@ -0,0 +1,139 @@ +Upstream: http://lists.gnu.org/archive/html/grub-devel/2009-09/msg00210.html +Description: If you set root after running loopback, any attempts to open + files on the loopback device resolve the loopback file name relative to the + *new* root, not the root at the time loopback was invoked, and so the above + recurses until it runs out of stack. This causes problems for Wubi. I think + it's fairly clear that only the root that was in place when you ran + loopback should be relevant to the loopback file name. + +diff -Nur -x '*.orig' -x '*~' grub2-1.97~beta2/disk/loopback.c grub2-1.97~beta2.new/disk/loopback.c +--- grub2-1.97~beta2/disk/loopback.c 2009-06-10 22:04:23.000000000 +0100 ++++ grub2-1.97~beta2.new/disk/loopback.c 2009-09-10 21:42:56.000000000 +0100 +@@ -28,6 +28,7 @@ + { + char *devname; + char *filename; ++ grub_file_t file; + int has_partitions; + struct grub_loopback *next; + }; +@@ -61,6 +62,7 @@ + /* Remove the device from the list. */ + *prev = dev->next; + ++ grub_file_close (dev->file); + grub_free (dev->devname); + grub_free (dev->filename); + grub_free (dev); +@@ -90,9 +92,6 @@ + if (! file) + return grub_errno; + +- /* Close the file, the only reason for opening it is validation. */ +- grub_file_close (file); +- + /* First try to replace the old device. */ + for (newdev = loopback_list; newdev; newdev = newdev->next) + if (grub_strcmp (newdev->devname, args[0]) == 0) +@@ -102,10 +101,12 @@ + { + char *newname = grub_strdup (args[1]); + if (! newname) +- return grub_errno; ++ goto fail; + + grub_free (newdev->filename); + newdev->filename = newname; ++ grub_file_close (newdev->file); ++ newdev->file = file; + + /* Set has_partitions when `--partitions' was used. */ + newdev->has_partitions = state[1].set; +@@ -116,13 +117,13 @@ + /* Unable to replace it, make a new entry. */ + newdev = grub_malloc (sizeof (struct grub_loopback)); + if (! newdev) +- return grub_errno; ++ goto fail; + + newdev->devname = grub_strdup (args[0]); + if (! newdev->devname) + { + grub_free (newdev); +- return grub_errno; ++ goto fail; + } + + newdev->filename = grub_strdup (args[1]); +@@ -130,9 +131,11 @@ + { + grub_free (newdev->devname); + grub_free (newdev); +- return grub_errno; ++ goto fail; + } + ++ newdev->file = file; ++ + /* Set has_partitions when `--partitions' was used. */ + newdev->has_partitions = state[1].set; + +@@ -141,6 +144,10 @@ + loopback_list = newdev; + + return 0; ++ ++fail: ++ grub_file_close (file); ++ return grub_errno; + } + + +@@ -159,7 +166,6 @@ + static grub_err_t + grub_loopback_open (const char *name, grub_disk_t disk) + { +- grub_file_t file; + struct grub_loopback *dev; + + for (dev = loopback_list; dev; dev = dev->next) +@@ -169,29 +175,17 @@ + if (! dev) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device"); + +- file = grub_file_open (dev->filename); +- if (! file) +- return grub_errno; +- + /* Use the filesize for the disk size, round up to a complete sector. */ +- disk->total_sectors = ((file->size + GRUB_DISK_SECTOR_SIZE - 1) ++ disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1) + / GRUB_DISK_SECTOR_SIZE); + disk->id = (unsigned long) dev; + + disk->has_partitions = dev->has_partitions; +- disk->data = file; ++ disk->data = dev->file; + + return 0; + } + +-static void +-grub_loopback_close (grub_disk_t disk) +-{ +- grub_file_t file = (grub_file_t) disk->data; +- +- grub_file_close (file); +-} +- + static grub_err_t + grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +@@ -233,7 +227,6 @@ + .id = GRUB_DISK_DEVICE_LOOPBACK_ID, + .iterate = grub_loopback_iterate, + .open = grub_loopback_open, +- .close = grub_loopback_close, + .read = grub_loopback_read, + .write = grub_loopback_write, + .next = 0 diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/957_handle_loopback.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/957_handle_loopback.diff new file mode 100644 index 00000000..0ee868fd --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/957_handle_loopback.diff @@ -0,0 +1,45 @@ +Ubuntu: needed for Wubi +Description: Change prepare_grub_to_access_device to handle filesystems + loop-mounted on file images. +UbuntuSpecific: Not inherently. losetup and /proc/mounts are Linux-specific, + though, so we might need to refine this before sending it upstream. + +diff -Nur -x '*.orig' -x '*~' grub2-1.97~beta3/util/grub-mkconfig_lib.in grub2-1.97~beta3.new/util/grub-mkconfig_lib.in +--- grub2-1.97~beta3/util/grub-mkconfig_lib.in 2009-09-15 00:23:50.000000000 +0100 ++++ grub2-1.97~beta3.new/util/grub-mkconfig_lib.in 2009-09-15 00:31:31.000000000 +0100 +@@ -142,6 +142,20 @@ + { + device=$1 + ++ loop_file= ++ case ${device} in ++ /dev/loop/*|/dev/loop[0-9]) ++ loop_file=`losetup ${device} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"` ++ case $loop_file in ++ /dev/*) ;; ++ *) ++ loop_device=${device} ++ device=`${grub_probe} --target=device "${loop_file}"` ++ ;; ++ esac ++ ;; ++ esac ++ + # Abstraction modules aren't auto-loaded. + abstraction="`${grub_probe} --device ${device} --target=abstraction`" + for module in ${abstraction} ; do +@@ -159,6 +173,14 @@ + if fs_uuid="`${grub_probe} --device ${device} --target=fs_uuid 2> /dev/null`" ; then + echo "search --no-floppy --fs-uuid --set ${fs_uuid}" + fi ++ ++ if [ "x${loop_file}" != x ]; then ++ loop_mountpoint="$(awk '"'${loop_file}'" ~ "^"$2 && $2 != "/" { print $2 }' /proc/mounts | tail -n1)" ++ if [ "x${loop_mountpoint}" != x ]; then ++ echo "loopback loop0 ${loop_file#$loop_mountpoint}" ++ echo "set root=(loop0)" ++ fi ++ fi + } + + grub_file_is_not_garbage () diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/958_linux_no_loopmount.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/958_linux_no_loopmount.diff new file mode 100644 index 00000000..9e0dfda9 --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/958_linux_no_loopmount.diff @@ -0,0 +1,20 @@ +Ubuntu: needed for Wubi +Description: Ignore devices loop-mounted from files in 10_linux. +UbuntuSpecific: Not inherently, but perhaps we should integrate 10_lupin + properly instead. + +diff -Nur -x '*.orig' -x '*~' grub2-1.97~beta3/util/grub.d/10_linux.in grub2-1.97~beta3.new/util/grub.d/10_linux.in +--- grub2-1.97~beta3/util/grub.d/10_linux.in 2009-09-16 17:41:06.000000000 +0100 ++++ grub2-1.97~beta3.new/util/grub.d/10_linux.in 2009-09-16 17:44:52.000000000 +0100 +@@ -32,6 +32,11 @@ + case ${GRUB_DEVICE} in + /dev/loop/*|/dev/loop[0-9]) + GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"` ++ # We can't cope with devices loop-mounted from files here. ++ case ${GRUB_DEVICE} in ++ /dev/*) ;; ++ *) exit 0 ;; ++ esac + ;; + esac + diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/960_raid_virtio.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/960_raid_virtio.diff new file mode 100644 index 00000000..3b060ba0 --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/960_raid_virtio.diff @@ -0,0 +1,158 @@ +diff -Nur -x '*.orig' -x '*~' grub2/include/grub/util/getroot.h grub2.new/include/grub/util/getroot.h +--- grub2/include/grub/util/getroot.h 2009-11-29 18:42:14.000000000 -0800 ++++ grub2.new/include/grub/util/getroot.h 2010-02-03 14:38:02.000000000 -0800 +@@ -19,12 +19,15 @@ + #ifndef GRUB_UTIL_GETROOT_HEADER + #define GRUB_UTIL_GETROOT_HEADER 1 + ++#include <sys/types.h> ++ + enum grub_dev_abstraction_types { + GRUB_DEV_ABSTRACTION_NONE, + GRUB_DEV_ABSTRACTION_LVM, + GRUB_DEV_ABSTRACTION_RAID, + }; + ++char *grub_find_device (const char *dir, dev_t dev); + char *grub_guess_root_device (const char *dir); + char *grub_get_prefix (const char *dir); + int grub_util_get_dev_abstraction (const char *os_dev); +diff -Nur -x '*.orig' -x '*~' grub2/util/getroot.c grub2.new/util/getroot.c +--- grub2/util/getroot.c 2010-02-01 14:33:16.000000000 -0800 ++++ grub2.new/util/getroot.c 2010-02-03 14:38:02.000000000 -0800 +@@ -178,8 +178,8 @@ + + #ifdef __MINGW32__ + +-static char * +-find_root_device (const char *dir __attribute__ ((unused)), ++char * ++grub_find_device (const char *dir __attribute__ ((unused)), + dev_t dev __attribute__ ((unused))) + { + return 0; +@@ -187,13 +187,22 @@ + + #elif ! defined(__CYGWIN__) + +-static char * +-find_root_device (const char *dir, dev_t dev) ++char * ++grub_find_device (const char *dir, dev_t dev) + { + DIR *dp; + char *saved_cwd; + struct dirent *ent; + ++ if (! dir) ++ { ++#ifdef __CYGWIN__ ++ return NULL; ++#else ++ dir = "/dev"; ++#endif ++ } ++ + dp = opendir (dir); + if (! dp) + return 0; +@@ -231,7 +240,7 @@ + /* Find it recursively. */ + char *res; + +- res = find_root_device (ent->d_name, dev); ++ res = grub_find_device (ent->d_name, dev); + + if (res) + { +@@ -334,8 +343,8 @@ + return serial; + } + +-static char * +-find_cygwin_root_device (const char *path, dev_t dev) ++char * ++grub_find_device (const char *path, dev_t dev) + { + /* No root device for /cygdrive. */ + if (dev == (DEV_CYGDRIVE_MAJOR << 16)) +@@ -356,7 +365,7 @@ + + /* Cygwin returns the partition serial number in stat.st_dev. + This is never identical to the device number of the emulated +- /dev/sdXN device, so above find_root_device () does not work. ++ /dev/sdXN device, so above grub_find_device () does not work. + Search the partition with the same serial in boot sector instead. */ + char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia. */ + int d; +@@ -449,12 +458,12 @@ + + #ifdef __CYGWIN__ + /* Cygwin specific function. */ +- os_dev = find_cygwin_root_device (dir, st.st_dev); ++ os_dev = grub_find_device (dir, st.st_dev); + + #else + + /* This might be truly slow, but is there any better way? */ +- os_dev = find_root_device ("/dev", st.st_dev); ++ os_dev = grub_find_device ("/dev", st.st_dev); + #endif + #endif /* !__GNU__ */ + +diff -Nur -x '*.orig' -x '*~' grub2/util/raid.c grub2.new/util/raid.c +--- grub2/util/raid.c 2010-02-01 14:33:15.000000000 -0800 ++++ grub2.new/util/raid.c 2010-02-03 14:39:38.000000000 -0800 +@@ -21,40 +21,19 @@ + #ifdef __linux__ + #include <grub/util/misc.h> + #include <grub/util/raid.h> ++#include <grub/util/getroot.h> + + #include <string.h> + #include <fcntl.h> + #include <sys/ioctl.h> + #include <errno.h> ++#include <sys/types.h> + + #include <linux/types.h> + #include <linux/major.h> + #include <linux/raid/md_p.h> + #include <linux/raid/md_u.h> + +-static char * +-grub_util_getdiskname (int major, int minor) +-{ +- char *name = xmalloc (15); +- +- if (major == LOOP_MAJOR) +- sprintf (name, "/dev/loop%d", minor); +- else if (major == IDE0_MAJOR) +- sprintf (name, "/dev/hd%c", 'a' + minor / 64); +- else if (major == IDE1_MAJOR) +- sprintf (name, "/dev/hd%c", 'c' + minor / 64); +- else if (major == IDE2_MAJOR) +- sprintf (name, "/dev/hd%c", 'e' + minor / 64); +- else if (major == IDE3_MAJOR) +- sprintf (name, "/dev/hd%c", 'g' + minor / 64); +- else if (major == SCSI_DISK0_MAJOR) +- sprintf (name, "/dev/sd%c", 'a' + minor / 16); +- else +- grub_util_error ("unknown device number: %d, %d", major, minor); +- +- return name; +-} +- + char ** + grub_util_raid_getmembers (char *name) + { +@@ -99,7 +78,8 @@ + + if (disk.state & (1 << MD_DISK_ACTIVE)) + { +- devicelist[j] = grub_util_getdiskname (disk.major, disk.minor); ++ devicelist[j] = grub_find_device (NULL, ++ makedev (disk.major, disk.minor)); + j++; + } + } diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/961_dmraid_probe.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/961_dmraid_probe.diff new file mode 100644 index 00000000..8bc94707 --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/961_dmraid_probe.diff @@ -0,0 +1,650 @@ +Description: Add DM-RAID probing support. +Upstream: Maintained in an upstream branch, + sftp://bzr.sv.gnu.org/srv/bzr/grub/branches/dmraid-probe/; see + http://lists.gnu.org/archive/html/grub-devel/2010-01/msg00345.html + +diff -Nur -x '*.orig' -x '*~' grub2/ChangeLog.dmraid-probe grub2.new/ChangeLog.dmraid-probe +--- grub2/ChangeLog.dmraid-probe 1969-12-31 16:00:00.000000000 -0800 ++++ grub2.new/ChangeLog.dmraid-probe 2010-02-06 10:33:54.000000000 -0800 +@@ -0,0 +1,26 @@ ++2010-01-31 Colin Watson <cjwatson@ubuntu.com> ++ ++ * configure.ac: Check for Linux device-mapper support. ++ ++ * util/hostdisk.c (device_is_mapped): New function. ++ (find_partition_start): New function, partly broken out from ++ linux_find_partition and grub_util_biosdisk_get_grub_dev but with ++ device-mapper support added. ++ (linux_find_partition): Use find_partition_start. ++ (convert_system_partition_to_system_disk): Add `st' argument. ++ Support Linux /dev/mapper/* devices if device-mapper support is ++ available; only DM-RAID devices are understood at present. ++ (find_system_device): Add `st' argument. Pass it to ++ convert_system_partition_to_system_disk. ++ (grub_util_biosdisk_get_grub_dev): Pass stat result to ++ find_system_device and convert_system_partition_to_system_disk. Use ++ find_partition_start. ++ ++ * conf/common.rmk (grub_mkdevicemap_SOURCES): Add kern/env.c, ++ kern/err.c, kern/list.c, and kern/misc.c. ++ * util/deviceiter.c [__linux__]: Define MINOR. ++ (grub_util_iterate_devices): Add support for DM-RAID disk devices. ++ * util/mkdevicemap.c (grub_putchar): New function. ++ (grub_getkey): New function. ++ (grub_refresh): New function. ++ (main): Set debug=all if -v -v is used. +diff -Nur -x '*.orig' -x '*~' grub2/conf/common.rmk grub2.new/conf/common.rmk +--- grub2/conf/common.rmk 2010-02-06 10:32:37.000000000 -0800 ++++ grub2.new/conf/common.rmk 2010-02-06 10:33:54.000000000 -0800 +@@ -3,7 +3,8 @@ + sbin_UTILITIES += grub-mkdevicemap + grub_mkdevicemap_SOURCES = gnulib/progname.c util/grub-mkdevicemap.c \ + util/deviceiter.c \ +- util/misc.c ++ util/misc.c \ ++ kern/env.c kern/err.c kern/list.c kern/misc.c + + ifeq ($(target_cpu)-$(platform), sparc64-ieee1275) + grub_mkdevicemap_SOURCES += util/ieee1275/ofpath.c util/ieee1275/devicemap.c +diff -Nur -x '*.orig' -x '*~' grub2/configure.ac grub2.new/configure.ac +--- grub2/configure.ac 2010-02-06 10:32:49.000000000 -0800 ++++ grub2.new/configure.ac 2010-02-06 10:33:54.000000000 -0800 +@@ -660,6 +660,22 @@ + AC_SUBST([freetype_cflags]) + AC_SUBST([freetype_libs]) + ++AC_ARG_ENABLE([device-mapper], ++ [AS_HELP_STRING([--enable-device-mapper], ++ [enable Linux device-mapper support (default=guessed)])]) ++if test x"$enable_device_mapper" = xno ; then ++ device_mapper_excuse="explicitly disabled" ++fi ++ ++if test x"$device_mapper_excuse" = x ; then ++ # Check for device-mapper library. ++ AC_CHECK_LIB([devmapper], [dm_task_create], ++ [LDFLAGS="$LDFLAGS -ldevmapper" ++ AC_DEFINE([HAVE_DEVICE_MAPPER], [1], ++ [Define to 1 if you have the devmapper library.])], ++ [device_mapper_excuse="need devmapper library"]) ++fi ++ + AC_SUBST(ASFLAGS) + + # Output files. +diff -Nur -x '*.orig' -x '*~' grub2/util/deviceiter.c grub2.new/util/deviceiter.c +--- grub2/util/deviceiter.c 2010-02-06 10:32:37.000000000 -0800 ++++ grub2.new/util/deviceiter.c 2010-02-06 10:33:54.000000000 -0800 +@@ -31,6 +31,8 @@ + + #include <grub/util/misc.h> + #include <grub/util/deviceiter.h> ++#include <grub/list.h> ++#include <grub/misc.h> + + #ifdef __linux__ + # if !defined(__GLIBC__) || \ +@@ -62,12 +64,23 @@ + | ((unsigned int) (__dev >> 32) & ~0xfff); \ + }) + # endif /* ! MAJOR */ ++# ifndef MINOR ++# define MINOR(dev) \ ++ ({ \ ++ unsigned long long __dev = (dev); \ ++ (unsigned) (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff); \ ++ }) ++# endif /* ! MINOR */ + # ifndef CDROM_GET_CAPABILITY + # define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */ + # endif /* ! CDROM_GET_CAPABILITY */ + # ifndef BLKGETSIZE + # define BLKGETSIZE _IO(0x12,96) /* return device size */ + # endif /* ! BLKGETSIZE */ ++ ++#ifdef HAVE_DEVICE_MAPPER ++# include <libdevmapper.h> ++#endif + #endif /* __linux__ */ + + /* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with +@@ -411,6 +424,16 @@ + return 1; + } + ++#ifdef __linux__ ++# ifdef HAVE_DEVICE_MAPPER ++struct dmraid_seen ++{ ++ struct dmraid_seen *next; ++ const char *name; ++}; ++# endif /* HAVE_DEVICE_MAPPER */ ++#endif /* __linux__ */ ++ + void + grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), + int floppy_disks) +@@ -643,6 +666,123 @@ + return; + } + } ++ ++# ifdef HAVE_DEVICE_MAPPER ++# define dmraid_check(cond, ...) \ ++ if (! (cond)) \ ++ { \ ++ grub_dprintf ("deviceiter", __VA_ARGS__); \ ++ goto dmraid_end; \ ++ } ++ ++ /* DM-RAID. */ ++ { ++ struct dm_tree *tree = NULL; ++ struct dm_task *task = NULL; ++ struct dm_names *names = NULL; ++ unsigned int next = 0; ++ void *top_handle, *second_handle; ++ struct dm_tree_node *root, *top, *second; ++ struct dmraid_seen *seen = NULL; ++ ++ /* Build DM tree for all devices. */ ++ tree = dm_tree_create (); ++ dmraid_check (tree, "dm_tree_create failed\n"); ++ task = dm_task_create (DM_DEVICE_LIST); ++ dmraid_check (task, "dm_task_create failed\n"); ++ dmraid_check (dm_task_run (task), "dm_task_run failed\n"); ++ names = dm_task_get_names (task); ++ dmraid_check (names, "dm_task_get_names failed\n"); ++ dmraid_check (names->dev, "No DM devices found\n"); ++ do ++ { ++ names = (void *) names + next; ++ dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev), ++ MINOR (names->dev)), ++ "dm_tree_add_dev (%s) failed\n", names->name); ++ next = names->next; ++ } ++ while (next); ++ ++ /* Walk the second-level children of the inverted tree; that is, devices ++ which are directly composed of non-DM devices such as hard disks. ++ This class includes all DM-RAID disks and excludes all DM-RAID ++ partitions. */ ++ root = dm_tree_find_node (tree, 0, 0); ++ top_handle = NULL; ++ top = dm_tree_next_child (&top_handle, root, 1); ++ while (top) ++ { ++ second_handle = NULL; ++ second = dm_tree_next_child (&second_handle, top, 1); ++ while (second) ++ { ++ const char *node_name, *node_uuid; ++ char *name; ++ struct dmraid_seen *seen_elt; ++ ++ node_name = dm_tree_node_get_name (second); ++ dmraid_check (node_name, "dm_tree_node_get_name failed\n"); ++ node_uuid = dm_tree_node_get_uuid (second); ++ dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n"); ++ if (strncmp (node_uuid, "DMRAID-", 7) != 0) ++ { ++ grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name); ++ goto dmraid_next_child; ++ } ++ ++ /* Have we already seen this node? There are typically very few ++ DM-RAID disks, so a list should be fast enough. */ ++ if (grub_named_list_find (GRUB_AS_NAMED_LIST (seen), node_name)) ++ { ++ grub_dprintf ("deviceiter", "Already seen DM device %s\n", ++ node_name); ++ goto dmraid_next_child; ++ } ++ ++ name = xasprintf ("/dev/mapper/%s", node_name); ++ if (check_device (name)) ++ { ++ if (hook (name, 0)) ++ { ++ free (name); ++ while (seen) ++ { ++ struct dmraid_seen *seen_elt = ++ grub_list_pop (GRUB_AS_LIST_P (&seen)); ++ free (seen_elt); ++ } ++ if (task) ++ dm_task_destroy (task); ++ if (tree) ++ dm_tree_free (tree); ++ return; ++ } ++ } ++ free (name); ++ ++ seen_elt = xmalloc (sizeof *seen_elt); ++ seen_elt->name = node_name; ++ grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt)); ++ ++dmraid_next_child: ++ second = dm_tree_next_child (&second_handle, top, 1); ++ } ++ top = dm_tree_next_child (&top_handle, root, 1); ++ } ++ ++dmraid_end: ++ while (seen) ++ { ++ struct dmraid_seen *seen_elt = grub_list_pop (GRUB_AS_LIST_P (&seen)); ++ free (seen_elt); ++ } ++ if (task) ++ dm_task_destroy (task); ++ if (tree) ++ dm_tree_free (tree); ++ } ++# endif /* HAVE_DEVICE_MAPPER */ + #endif /* __linux__ */ + } + +diff -Nur -x '*.orig' -x '*~' grub2/util/grub-mkdevicemap.c grub2.new/util/grub-mkdevicemap.c +--- grub2/util/grub-mkdevicemap.c 2010-02-06 10:32:37.000000000 -0800 ++++ grub2.new/util/grub-mkdevicemap.c 2010-02-06 10:33:54.000000000 -0800 +@@ -31,6 +31,7 @@ + + #include <grub/util/misc.h> + #include <grub/util/deviceiter.h> ++#include <grub/env.h> + #include <grub/i18n.h> + + #define _GNU_SOURCE 1 +@@ -38,6 +39,24 @@ + + #include "progname.h" + ++void ++grub_putchar (int c) ++{ ++ putchar (c); ++} ++ ++int ++grub_getkey (void) ++{ ++ return -1; ++} ++ ++void ++grub_refresh (void) ++{ ++ fflush (stdout); ++} ++ + static void + make_device_map (const char *device_map, int floppy_disks) + { +@@ -158,6 +177,9 @@ + } + } + ++ if (verbosity > 1) ++ grub_env_set ("debug", "all"); ++ + make_device_map (dev_map ? : DEFAULT_DEVICE_MAP, floppy_disks); + + free (dev_map); +diff -Nur -x '*.orig' -x '*~' grub2/util/hostdisk.c grub2.new/util/hostdisk.c +--- grub2/util/hostdisk.c 2010-02-06 10:32:55.000000000 -0800 ++++ grub2.new/util/hostdisk.c 2010-02-06 10:33:54.000000000 -0800 +@@ -97,6 +97,10 @@ + # include <sys/disk.h> + #endif + ++#ifdef HAVE_DEVICE_MAPPER ++# include <libdevmapper.h> ++#endif ++ + struct + { + char *drive; +@@ -253,6 +257,115 @@ + return GRUB_ERR_NONE; + } + ++#ifdef HAVE_DEVICE_MAPPER ++static int ++device_is_mapped (const char *dev) ++{ ++ struct stat st; ++ ++ if (stat (dev, &st) < 0) ++ return 0; ++ ++ return dm_is_dm_major (major (st.st_rdev)); ++} ++#endif /* HAVE_DEVICE_MAPPER */ ++ ++#if defined(__linux__) || defined(__CYGWIN__) ++static grub_disk_addr_t ++find_partition_start (const char *dev) ++{ ++ int fd; ++ struct hd_geometry hdg; ++ ++#ifdef HAVE_DEVICE_MAPPER ++ if (device_is_mapped (dev)) { ++ struct dm_task *task = NULL; ++ grub_uint64_t start, length; ++ char *target_type, *params, *space; ++ grub_disk_addr_t partition_start; ++ ++ /* If any device-mapper operation fails, we fall back silently to ++ HDIO_GETGEO. */ ++ task = dm_task_create (DM_DEVICE_TABLE); ++ if (! task) ++ { ++ grub_dprintf ("hostdisk", "dm_task_create failed\n"); ++ goto devmapper_fail; ++ } ++ ++ if (! dm_task_set_name (task, dev)) ++ { ++ grub_dprintf ("hostdisk", "dm_task_set_name failed\n"); ++ goto devmapper_fail; ++ } ++ ++ if (! dm_task_run (task)) ++ { ++ grub_dprintf ("hostdisk", "dm_task_run failed\n"); ++ goto devmapper_fail; ++ } ++ ++ dm_get_next_target (task, NULL, &start, &length, &target_type, ¶ms); ++ if (! target_type) ++ { ++ grub_dprintf ("hostdisk", "no dm target\n"); ++ goto devmapper_fail; ++ } ++ if (strcmp (target_type, "linear") != 0) ++ { ++ grub_dprintf ("hostdisk", "ignoring dm target %s (not linear)\n", ++ target_type); ++ goto devmapper_fail; ++ } ++ if (! params) ++ { ++ grub_dprintf ("hostdisk", "no dm params\n"); ++ goto devmapper_fail; ++ } ++ ++ /* The params string for a linear target looks like this: ++ DEVICE-NAME START-SECTOR ++ Parse this out. */ ++ space = strchr (params, ' '); ++ if (! space) ++ goto devmapper_fail; ++ errno = 0; ++ partition_start = strtoull (space + 1, NULL, 10); ++ if (errno == 0) ++ { ++ grub_dprintf ("hostdisk", "dm %s starts at %llu\n", ++ dev, partition_start); ++ dm_task_destroy (task); ++ return partition_start; ++ } ++ ++devmapper_fail: ++ if (task) ++ dm_task_destroy (task); ++ } ++#endif /* HAVE_DEVICE_MAPPER */ ++ ++ fd = open (dev, O_RDONLY); ++ if (fd == -1) ++ { ++ grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", dev); ++ return 0; ++ } ++ ++ if (ioctl (fd, HDIO_GETGEO, &hdg)) ++ { ++ grub_error (GRUB_ERR_BAD_DEVICE, ++ "cannot get geometry of `%s'", dev); ++ close (fd); ++ return 0; ++ } ++ ++ close (fd); ++ ++ return hdg.start; ++} ++#endif /* __linux__ || __CYGWIN__ */ ++ + #ifdef __linux__ + static int + linux_find_partition (char *dev, unsigned long sector) +@@ -284,22 +397,20 @@ + for (i = 1; i < 10000; i++) + { + int fd; +- struct hd_geometry hdg; ++ grub_disk_addr_t start; + + sprintf (p, format, i); ++ + fd = open (real_dev, O_RDONLY); + if (fd == -1) + return 0; +- +- if (ioctl (fd, HDIO_GETGEO, &hdg)) +- { +- close (fd); +- return 0; +- } +- + close (fd); + +- if (hdg.start == sector) ++ start = find_partition_start (real_dev); ++ /* We don't care about errors here. */ ++ grub_errno = GRUB_ERR_NONE; ++ ++ if (start == sector) + { + strcpy (dev, real_dev); + return 1; +@@ -711,7 +822,7 @@ + } + + static char * +-convert_system_partition_to_system_disk (const char *os_dev) ++convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) + { + #if defined(__linux__) + char *path = xmalloc (PATH_MAX); +@@ -829,6 +940,96 @@ + p[4] = '\0'; + return path; + } ++ ++#ifdef HAVE_DEVICE_MAPPER ++ /* If this is a DM-RAID device. */ ++ if ((strncmp ("mapper/", p, 7) == 0)) ++ { ++ static struct dm_tree *tree = NULL; ++ uint32_t maj, min; ++ struct dm_tree_node *node, *child; ++ void *handle; ++ const char *node_uuid, *mapper_name, *child_uuid, *child_name; ++ ++ if (! tree) ++ tree = dm_tree_create (); ++ ++ if (! tree) ++ { ++ grub_dprintf ("hostdisk", "dm_tree_create failed\n"); ++ return NULL; ++ } ++ ++ maj = major (st->st_rdev); ++ min = minor (st->st_rdev); ++ if (! dm_tree_add_dev (tree, maj, min)) ++ { ++ grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); ++ return NULL; ++ } ++ ++ node = dm_tree_find_node (tree, maj, min); ++ if (! node) ++ { ++ grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); ++ return NULL; ++ } ++ node_uuid = dm_tree_node_get_uuid (node); ++ if (! node_uuid) ++ { ++ grub_dprintf ("hostdisk", "%s has no DM uuid\n", path); ++ return NULL; ++ } ++ else if (strncmp (node_uuid, "DMRAID-", 7) != 0) ++ { ++ grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path); ++ return NULL; ++ } ++ ++ handle = NULL; ++ mapper_name = NULL; ++ /* Counter-intuitively, device-mapper refers to the disk-like ++ device containing a DM-RAID partition device as a "child" of ++ the partition device. */ ++ child = dm_tree_next_child (&handle, node, 0); ++ if (! child) ++ { ++ grub_dprintf ("hostdisk", "%s has no DM children\n", path); ++ goto devmapper_out; ++ } ++ child_uuid = dm_tree_node_get_uuid (child); ++ if (! child_uuid) ++ { ++ grub_dprintf ("hostdisk", "%s child has no DM uuid\n", path); ++ goto devmapper_out; ++ } ++ else if (strncmp (child_uuid, "DMRAID-", 7) != 0) ++ { ++ grub_dprintf ("hostdisk", "%s child is not DM-RAID\n", path); ++ goto devmapper_out; ++ } ++ child_name = dm_tree_node_get_name (child); ++ if (! child_name) ++ { ++ grub_dprintf ("hostdisk", "%s child has no DM name\n", path); ++ goto devmapper_out; ++ } ++ mapper_name = child_name; ++ ++devmapper_out: ++ if (! mapper_name) ++ { ++ /* This is a DM-RAID disk, not a partition. */ ++ mapper_name = dm_tree_node_get_name (node); ++ if (! mapper_name) ++ { ++ grub_dprintf ("hostdisk", "%s has no DM name\n", path); ++ return NULL; ++ } ++ } ++ return xasprintf ("/dev/mapper/%s", mapper_name); ++ } ++#endif /* HAVE_DEVICE_MAPPER */ + } + + return path; +@@ -884,12 +1085,12 @@ + #endif + + static int +-find_system_device (const char *os_dev) ++find_system_device (const char *os_dev, struct stat *st) + { + unsigned int i; + char *os_disk; + +- os_disk = convert_system_partition_to_system_disk (os_dev); ++ os_disk = convert_system_partition_to_system_disk (os_dev, st); + if (! os_disk) + return -1; + +@@ -923,7 +1124,7 @@ + return 0; + } + +- drive = find_system_device (os_dev); ++ drive = find_system_device (os_dev, &st); + if (drive < 0) + { + grub_error (GRUB_ERR_BAD_DEVICE, +@@ -931,8 +1132,8 @@ + return 0; + } + +- if (grub_strcmp (os_dev, convert_system_partition_to_system_disk (os_dev)) +- == 0) ++ if (grub_strcmp (os_dev, ++ convert_system_partition_to_system_disk (os_dev, &st)) == 0) + return make_device_name (drive, -1, -1); + + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) +@@ -954,8 +1155,7 @@ + { + char *name; + grub_disk_t disk; +- int fd; +- struct hd_geometry hdg; ++ grub_disk_addr_t start; + int dos_part = -1; + int bsd_part = -1; + auto int find_partition (grub_disk_t disk, +@@ -985,7 +1185,7 @@ + partition->index, partition->start); + } + +- if (hdg.start == partition->start) ++ if (start == partition->start) + { + if (pcdata) + { +@@ -1008,28 +1208,16 @@ + if (MAJOR (st.st_rdev) == FLOPPY_MAJOR) + return name; + +- fd = open (os_dev, O_RDONLY); +- if (fd == -1) +- { +- grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", os_dev); +- free (name); +- return 0; +- } +- +- if (ioctl (fd, HDIO_GETGEO, &hdg)) ++ start = find_partition_start (os_dev); ++ if (grub_errno != GRUB_ERR_NONE) + { +- grub_error (GRUB_ERR_BAD_DEVICE, +- "cannot get geometry of `%s'", os_dev); +- close (fd); + free (name); + return 0; + } + +- close (fd); +- +- grub_util_info ("%s starts from %lu", os_dev, hdg.start); ++ grub_util_info ("%s starts from %lu", os_dev, start); + +- if (hdg.start == 0 && device_is_wholedisk (os_dev)) ++ if (start == 0 && device_is_wholedisk (os_dev)) + return name; + + grub_util_info ("opening the device %s", name); diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/962_no_device_map.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/962_no_device_map.diff new file mode 100644 index 00000000..c129254a --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/962_no_device_map.diff @@ -0,0 +1,112 @@ +Ubuntu: Don't generate a device map by default. + +diff -Nur -x '*.orig' -x '*~' grub2/util/grub-install.in grub2.new/util/grub-install.in +--- grub2/util/grub-install.in 2010-03-22 14:11:42.000000000 +0000 ++++ grub2.new/util/grub-install.in 2010-03-22 16:23:14.000000000 +0000 +@@ -39,7 +39,6 @@ + else + grub_mkimage=${bindir}/`echo grub-mkelfimage | sed ${transform}` + fi +-grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` + grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` + grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` + rootdir= +@@ -74,7 +73,6 @@ + instead of the root directory + --grub-setup=FILE use FILE as grub-setup + --grub-mkimage=FILE use FILE as grub-mkimage +- --grub-mkdevicemap=FILE use FILE as grub-mkdevicemap + --grub-probe=FILE use FILE as grub-probe + --no-floppy do not probe any floppy drive + --recheck probe a device map even if it already exists +@@ -124,7 +122,7 @@ + --grub-mkimage=*) + grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + --grub-mkdevicemap=*) +- grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; ++ : ;; # compatibility only + --grub-probe=*) + grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; + --no-floppy) +@@ -209,14 +207,6 @@ + exit 1 + fi + +-set $grub_mkdevicemap dummy +-if test -f "$1"; then +- : +-else +- echo "$1: Not found." 1>&2 +- exit 1 +-fi +- + # Create the GRUB directory if it is not present. + test -d "$bootdir" || mkdir "$bootdir" || exit 1 + test -d "$grubdir" || mkdir "$grubdir" || exit 1 +@@ -226,22 +216,14 @@ + rm -f $device_map + fi + +-# Create the device map file if it is not present. ++# Make sure that there is no duplicated entry in the device map. + if test -f "$device_map"; then +- : +-else +- # Create a safe temporary file. +- test -n "$mklog" && log_file=`$mklog` +- +- $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1 +-fi +- +-# Make sure that there is no duplicated entry. +-tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \ +- | sort | uniq -d | sed -n 1p` +-if test -n "$tmp"; then +- echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2 +- exit 1 ++ tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \ ++ | sort | uniq -d | sed -n 1p` ++ if test -n "$tmp"; then ++ echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2 ++ exit 1 ++ fi + fi + + # Copy the GRUB images to the GRUB directory. +diff -Nur -x '*.orig' -x '*~' grub2/util/grub-mkconfig.in grub2.new/util/grub-mkconfig.in +--- grub2/util/grub-mkconfig.in 2010-03-22 16:23:13.000000000 +0000 ++++ grub2.new/util/grub-mkconfig.in 2010-03-22 16:23:57.000000000 +0000 +@@ -31,7 +31,6 @@ + grub_cfg="" + grub_mkconfig_dir=${sysconfdir}/grub.d + +-grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` + grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` + + # Usage: usage +@@ -96,14 +95,6 @@ + fi + fi + +-set $grub_mkdevicemap dummy +-if test -f "$1"; then +- : +-else +- echo "$1: Not found." 1>&2 +- exit 1 +-fi +- + set $grub_probe dummy + if test -f "$1"; then + : +@@ -114,10 +105,6 @@ + + mkdir -p ${grub_prefix} + +-if test -e ${grub_prefix}/device.map ; then : ; else +- ${grub_mkdevicemap} +-fi +- + # Device containing our userland. Typically used for root= parameter. + GRUB_DEVICE="`${grub_probe} --target=device /`" + GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/968_hostdisk_speedup.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/968_hostdisk_speedup.diff new file mode 100644 index 00000000..30ebcbea --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/968_hostdisk_speedup.diff @@ -0,0 +1,310 @@ +Upstream: http://lists.gnu.org/archive/html/grub-devel/2010-03/msg00008.html +Description: Optimise hostdisk device handling + This substantially speeds up grub-probe filesystem reads. + +diff -Nur -x '*.orig' -x '*~' grub2/ChangeLog.hostdisk-speedup grub2.new/ChangeLog.hostdisk-speedup +--- grub2/ChangeLog.hostdisk-speedup 1970-01-01 01:00:00.000000000 +0100 ++++ grub2.new/ChangeLog.hostdisk-speedup 2010-03-03 10:43:43.000000000 +0000 +@@ -0,0 +1,18 @@ ++2010-03-03 Colin Watson <cjwatson@ubuntu.com> ++ ++ * util/hostdisk.c (struct grub_util_biosdisk_data): New structure. ++ (grub_util_biosdisk_open): Initialise disk->data. ++ (struct linux_partition_cache): New structure. ++ (linux_find_partition): Cache partition start positions; these are ++ expensive to compute on every read and write. ++ (open_device): Cache open file descriptor in disk->data, so that we ++ don't have to reopen it and flush the buffer cache for consecutive ++ operations on the same device. ++ (grub_util_biosdisk_close): New function. ++ (grub_util_biosdisk_dev): Set `close' member. ++ ++ * conf/common.rmk (grub_probe_SOURCES): Add kern/list.c. ++ * conf/i386-efi.rmk (grub_setup_SOURCES): Likewise. ++ * conf/i386-pc.rmk (grub_setup_SOURCES): Likewise. ++ * conf/sparc64-ieee1275.rmk (grub_setup_SOURCES): Likewise. ++ * conf/x86_64-efi.rmk (grub_setup_SOURCES): Likewise. +diff -Nur -x '*.orig' -x '*~' grub2/conf/common.rmk grub2.new/conf/common.rmk +--- grub2/conf/common.rmk 2010-03-03 20:11:04.000000000 +0000 ++++ grub2.new/conf/common.rmk 2010-03-03 20:11:05.000000000 +0000 +@@ -25,7 +25,7 @@ + grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c \ + util/hostdisk.c util/misc.c util/getroot.c \ + kern/device.c kern/disk.c kern/err.c kern/misc.c \ +- kern/parser.c kern/partition.c kern/file.c \ ++ kern/parser.c kern/partition.c kern/file.c kern/list.c \ + \ + fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c \ + fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \ +diff -Nur -x '*.orig' -x '*~' grub2/conf/i386-efi.rmk grub2.new/conf/i386-efi.rmk +--- grub2/conf/i386-efi.rmk 2010-03-03 20:08:04.000000000 +0000 ++++ grub2.new/conf/i386-efi.rmk 2010-03-03 20:11:05.000000000 +0000 +@@ -21,7 +21,7 @@ + # kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c \ + # fs/sfs.c kern/parser.c kern/partition.c partmap/msdos.c \ + # fs/ufs.c fs/ufs2.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c \ +-# kern/fs.c kern/env.c fs/fshelp.c ++# kern/fs.c kern/env.c kern/list.c fs/fshelp.c + + # Scripts. + sbin_SCRIPTS = grub-install +diff -Nur -x '*.orig' -x '*~' grub2/conf/i386-pc.rmk grub2.new/conf/i386-pc.rmk +--- grub2/conf/i386-pc.rmk 2010-03-03 20:08:04.000000000 +0000 ++++ grub2.new/conf/i386-pc.rmk 2010-03-03 20:11:05.000000000 +0000 +@@ -96,7 +96,8 @@ + util/i386/pc/grub-setup.c util/hostdisk.c \ + util/misc.c util/getroot.c kern/device.c kern/disk.c \ + kern/err.c kern/misc.c kern/parser.c kern/partition.c \ +- kern/file.c kern/fs.c kern/env.c fs/fshelp.c \ ++ kern/file.c kern/fs.c kern/env.c kern/list.c \ ++ fs/fshelp.c \ + \ + fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \ + fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \ +diff -Nur -x '*.orig' -x '*~' grub2/conf/sparc64-ieee1275.rmk grub2.new/conf/sparc64-ieee1275.rmk +--- grub2/conf/sparc64-ieee1275.rmk 2010-03-03 20:08:04.000000000 +0000 ++++ grub2.new/conf/sparc64-ieee1275.rmk 2010-03-03 20:11:05.000000000 +0000 +@@ -70,7 +70,8 @@ + grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c util/hostdisk.c \ + util/misc.c util/getroot.c kern/device.c kern/disk.c \ + kern/err.c kern/misc.c kern/parser.c kern/partition.c \ +- kern/file.c kern/fs.c kern/env.c fs/fshelp.c \ ++ kern/file.c kern/fs.c kern/env.c kern/list.c \ ++ fs/fshelp.c \ + \ + fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \ + fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \ +diff -Nur -x '*.orig' -x '*~' grub2/conf/x86_64-efi.rmk grub2.new/conf/x86_64-efi.rmk +--- grub2/conf/x86_64-efi.rmk 2010-03-03 20:08:04.000000000 +0000 ++++ grub2.new/conf/x86_64-efi.rmk 2010-03-03 20:11:05.000000000 +0000 +@@ -20,7 +20,7 @@ + # kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c \ + # fs/sfs.c kern/parser.c kern/partition.c partmap/msdos.c \ + # fs/ufs.c fs/ufs2.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c \ +-# kern/fs.c kern/env.c fs/fshelp.c ++# kern/fs.c kern/env.c kern/list.c fs/fshelp.c + + # Scripts. + sbin_SCRIPTS = grub-install +diff -Nur -x '*.orig' -x '*~' grub2/util/hostdisk.c grub2.new/util/hostdisk.c +--- grub2/util/hostdisk.c 2010-03-03 20:11:04.000000000 +0000 ++++ grub2.new/util/hostdisk.c 2010-03-03 20:11:05.000000000 +0000 +@@ -26,6 +26,7 @@ + #include <grub/util/hostdisk.h> + #include <grub/misc.h> + #include <grub/i18n.h> ++#include <grub/list.h> + + #include <stdio.h> + #include <stdlib.h> +@@ -107,6 +108,13 @@ + char *device; + } map[256]; + ++struct grub_util_biosdisk_data ++{ ++ char *dev; ++ int access_mode; ++ int fd; ++}; ++ + #ifdef __linux__ + /* Check if we have devfs support. */ + static int +@@ -169,6 +177,7 @@ + { + int drive; + struct stat st; ++ struct grub_util_biosdisk_data *data; + + drive = find_grub_drive (name); + if (drive < 0) +@@ -177,6 +186,10 @@ + + disk->has_partitions = 1; + disk->id = drive; ++ disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data)); ++ data->dev = NULL; ++ data->access_mode = 0; ++ data->fd = -1; + + /* Get the size. */ + #if defined(__MINGW32__) +@@ -367,6 +380,17 @@ + #endif /* __linux__ || __CYGWIN__ */ + + #ifdef __linux__ ++/* Cache of partition start sectors for each disk. */ ++struct linux_partition_cache ++{ ++ struct linux_partition_cache *next; ++ char *dev; ++ unsigned long start; ++ int partno; ++}; ++ ++struct linux_partition_cache *linux_partition_cache_list; ++ + static int + linux_find_partition (char *dev, unsigned long sector) + { +@@ -375,6 +399,7 @@ + char *p; + int i; + char real_dev[PATH_MAX]; ++ struct linux_partition_cache *cache; + + strcpy(real_dev, dev); + +@@ -394,6 +419,16 @@ + format = "%d"; + } + ++ for (cache = linux_partition_cache_list; cache; cache = cache->next) ++ { ++ if (strcmp (cache->dev, dev) == 0 && cache->start == sector) ++ { ++ sprintf (p, format, cache->partno); ++ strcpy (dev, real_dev); ++ return 1; ++ } ++ } ++ + for (i = 1; i < 10000; i++) + { + int fd; +@@ -412,6 +447,15 @@ + + if (start == sector) + { ++ struct linux_partition_cache *new_cache_item; ++ ++ new_cache_item = xmalloc (sizeof *new_cache_item); ++ new_cache_item->dev = xstrdup (dev); ++ new_cache_item->start = start; ++ new_cache_item->partno = i; ++ grub_list_push (GRUB_AS_LIST_P (&linux_partition_cache_list), ++ GRUB_AS_LIST (new_cache_item)); ++ + strcpy (dev, real_dev); + return 1; + } +@@ -425,6 +469,7 @@ + open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) + { + int fd; ++ struct grub_util_biosdisk_data *data = disk->data; + + #ifdef O_LARGEFILE + flags |= O_LARGEFILE; +@@ -451,18 +496,35 @@ + && strncmp (map[disk->id].device, "/dev/", 5) == 0) + is_partition = linux_find_partition (dev, disk->partition->start); + +- /* Open the partition. */ +- grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev); +- fd = open (dev, flags); +- if (fd < 0) ++ if (data->dev && strcmp (data->dev, dev) == 0 && ++ data->access_mode == (flags & O_ACCMODE)) + { +- grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", dev); +- return -1; ++ grub_dprintf ("hostdisk", "reusing open device `%s'\n", dev); ++ fd = data->fd; + } ++ else ++ { ++ free (data->dev); ++ if (data->fd != -1) ++ close (data->fd); ++ ++ /* Open the partition. */ ++ grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev); ++ fd = open (dev, flags); ++ if (fd < 0) ++ { ++ grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", dev); ++ return -1; ++ } + +- /* Flush the buffer cache to the physical disk. +- XXX: This also empties the buffer cache. */ +- ioctl (fd, BLKFLSBUF, 0); ++ /* Flush the buffer cache to the physical disk. ++ XXX: This also empties the buffer cache. */ ++ ioctl (fd, BLKFLSBUF, 0); ++ ++ data->dev = xstrdup (dev); ++ data->access_mode = (flags & O_ACCMODE); ++ data->fd = fd; ++ } + + if (is_partition) + sector -= disk->partition->start; +@@ -486,7 +548,26 @@ + } + #endif + +- fd = open (map[disk->id].device, flags); ++ if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 && ++ data->access_mode == (flags & O_ACCMODE)) ++ { ++ grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev); ++ fd = data->fd; ++ } ++ else ++ { ++ free (data->dev); ++ if (data->fd != -1) ++ close (data->fd); ++ ++ fd = open (map[disk->id].device, flags); ++ if (fd >= 0) ++ { ++ data->dev = xstrdup (map[disk->id].device); ++ data->access_mode = (flags & O_ACCMODE); ++ data->fd = fd; ++ } ++ } + + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + if (! (sysctl_oldflags & 0x10) +@@ -646,7 +727,6 @@ + != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device); + +- close (fd); + return grub_errno; + } + +@@ -681,17 +761,27 @@ + != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device); + +- close (fd); + return grub_errno; + } + ++static void ++grub_util_biosdisk_close (struct grub_disk *disk) ++{ ++ struct grub_util_biosdisk_data *data = disk->data; ++ ++ free (data->dev); ++ if (data->fd != -1) ++ close (data->fd); ++ free (data); ++} ++ + static struct grub_disk_dev grub_util_biosdisk_dev = + { + .name = "biosdisk", + .id = GRUB_DISK_DEVICE_BIOSDISK_ID, + .iterate = grub_util_biosdisk_iterate, + .open = grub_util_biosdisk_open, +- .close = 0, ++ .close = grub_util_biosdisk_close, + .read = grub_util_biosdisk_read, + .write = grub_util_biosdisk_write, + .next = 0 diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/969_lvm_raid_probe.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/969_lvm_raid_probe.diff new file mode 100644 index 00000000..52a5c44b --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/969_lvm_raid_probe.diff @@ -0,0 +1,227 @@ +Description: Fix LVM/RAID probing without device.map + When probing LVM or RAID without a device.map, probe all devices in order + that we will know about the underlying physical volumes. +Bug-Ubuntu: https://bugs.launchpad.net/bugs/525085 +Forwarded: http://lists.gnu.org/archive/html/grub-devel/2010-03/msg00084.html +Last-Update: 2010-03-22 + +diff -Nur -x '*.orig' -x '*~' grub2/conf/common.rmk grub2.new/conf/common.rmk +--- grub2/conf/common.rmk 2010-03-22 13:49:14.000000000 +0000 ++++ grub2.new/conf/common.rmk 2010-03-22 13:53:20.000000000 +0000 +@@ -24,6 +24,7 @@ + util/grub-probe.c_DEPENDENCIES = grub_probe_init.h + grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c \ + util/hostdisk.c util/misc.c util/getroot.c \ ++ util/deviceiter.c \ + kern/device.c kern/disk.c kern/err.c kern/misc.c \ + kern/parser.c kern/partition.c kern/file.c kern/list.c \ + \ +diff -Nur -x '*.orig' -x '*~' grub2/conf/i386-pc.rmk grub2.new/conf/i386-pc.rmk +--- grub2/conf/i386-pc.rmk 2010-03-22 13:49:14.000000000 +0000 ++++ grub2.new/conf/i386-pc.rmk 2010-03-22 13:49:17.000000000 +0000 +@@ -94,7 +94,8 @@ + util/i386/pc/grub-setup.c_DEPENDENCIES = grub_setup_init.h + grub_setup_SOURCES = gnulib/progname.c \ + util/i386/pc/grub-setup.c util/hostdisk.c \ +- util/misc.c util/getroot.c kern/device.c kern/disk.c \ ++ util/misc.c util/getroot.c util/deviceiter.c \ ++ kern/device.c kern/disk.c \ + kern/err.c kern/misc.c kern/parser.c kern/partition.c \ + kern/file.c kern/fs.c kern/env.c kern/list.c \ + fs/fshelp.c \ +diff -Nur -x '*.orig' -x '*~' grub2/conf/sparc64-ieee1275.rmk grub2.new/conf/sparc64-ieee1275.rmk +--- grub2/conf/sparc64-ieee1275.rmk 2010-03-22 13:49:14.000000000 +0000 ++++ grub2.new/conf/sparc64-ieee1275.rmk 2010-03-22 13:49:17.000000000 +0000 +@@ -68,7 +68,8 @@ + # For grub-setup. + util/sparc64/ieee1275/grub-setup.c_DEPENDENCIES = grub_setup_init.h + grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c util/hostdisk.c \ +- util/misc.c util/getroot.c kern/device.c kern/disk.c \ ++ util/misc.c util/getroot.c util/deviceiter.c \ ++ kern/device.c kern/disk.c \ + kern/err.c kern/misc.c kern/parser.c kern/partition.c \ + kern/file.c kern/fs.c kern/env.c kern/list.c \ + fs/fshelp.c \ +diff -Nur -x '*.orig' -x '*~' grub2/include/grub/util/hostdisk.h grub2.new/include/grub/util/hostdisk.h +--- grub2/include/grub/util/hostdisk.h 2010-03-22 13:47:27.000000000 +0000 ++++ grub2.new/include/grub/util/hostdisk.h 2010-03-22 13:51:33.000000000 +0000 +@@ -22,6 +22,7 @@ + + void grub_util_biosdisk_init (const char *dev_map); + void grub_util_biosdisk_fini (void); ++int grub_util_biosdisk_probe_device (const char *name, int is_floppy); + char *grub_util_biosdisk_get_grub_dev (const char *os_dev); + + #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ +diff -Nur -x '*.orig' -x '*~' grub2/util/grub-probe.c grub2.new/util/grub-probe.c +--- grub2/util/grub-probe.c 2010-03-22 13:47:27.000000000 +0000 ++++ grub2.new/util/grub-probe.c 2010-03-22 13:53:10.000000000 +0000 +@@ -28,6 +28,7 @@ + #include <grub/msdos_partition.h> + #include <grub/util/hostdisk.h> + #include <grub/util/getroot.h> ++#include <grub/util/deviceiter.h> + #include <grub/term.h> + #include <grub/env.h> + #include <grub/raid.h> +@@ -106,13 +107,14 @@ + } + + static void +-probe (const char *path, char *device_name) ++probe (const char *path, char *device_name, const char *dev_map) + { + char *drive_name = NULL; + char *grub_path = NULL; + char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL; + grub_device_t dev = NULL; + grub_fs_t fs; ++ struct stat dev_map_stat; + + if (path == NULL) + { +@@ -136,6 +138,22 @@ + goto end; + } + ++ if (stat (dev_map, &dev_map_stat) == -1 && ++ grub_util_get_dev_abstraction (device_name) != GRUB_DEV_ABSTRACTION_NONE) ++ { ++ /* If we don't have a device map, then we won't yet know about the ++ physical volumes underlying this device, so probe all devices. */ ++ grub_util_iterate_devices (grub_util_biosdisk_probe_device, 0); ++ ++ /* Now reinitialise the higher layers. */ ++ grub_lvm_fini (); ++ grub_mdraid_fini (); ++ grub_raid_fini (); ++ grub_raid_init (); ++ grub_mdraid_init (); ++ grub_lvm_init (); ++ } ++ + drive_name = grub_util_get_grub_dev (device_name); + if (! drive_name) + grub_util_error ("cannot find a GRUB drive for %s. Check your device.map", device_name); +@@ -428,9 +446,9 @@ + + /* Do it. */ + if (argument_is_device) +- probe (NULL, argument); ++ probe (NULL, argument, dev_map ? : DEFAULT_DEVICE_MAP); + else +- probe (argument, NULL); ++ probe (argument, NULL, dev_map ? : DEFAULT_DEVICE_MAP); + + /* Free resources. */ + grub_fini_all (); +diff -Nur -x '*.orig' -x '*~' grub2/util/hostdisk.c grub2.new/util/hostdisk.c +--- grub2/util/hostdisk.c 2010-03-22 13:49:14.000000000 +0000 ++++ grub2.new/util/hostdisk.c 2010-03-22 13:51:53.000000000 +0000 +@@ -1237,6 +1237,48 @@ + return i; + } + ++static void ++store_grub_dev (const char *grub_disk, const char *os_disk) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE (map); i++) ++ if (! map[i].device) ++ break; ++ else if (strcmp (map[i].drive, grub_disk) == 0) ++ { ++ if (strcmp (map[i].device, os_disk) == 0) ++ return; ++ grub_util_error (_("drive `%s' already mapped to `%s'"), ++ map[i].drive, map[i].device); ++ } ++ ++ if (i == ARRAY_SIZE (map)) ++ grub_util_error (_("device count exceeds limit")); ++ ++ map[i].drive = xstrdup (grub_disk); ++ map[i].device = xstrdup (os_disk); ++} ++ ++static int num_hd = 0; ++static int num_fd = 0; ++ ++int ++grub_util_biosdisk_probe_device (const char *name, int is_floppy) ++{ ++ char *grub_disk; ++ ++ if (is_floppy) ++ grub_disk = xasprintf ("fd%d", num_fd++); ++ else ++ grub_disk = xasprintf ("hd%d", num_hd++); ++ ++ store_grub_dev (grub_disk, name); ++ free (grub_disk); ++ ++ return 0; ++} ++ + char * + grub_util_biosdisk_get_grub_dev (const char *os_dev) + { +diff -Nur -x '*.orig' -x '*~' grub2/util/i386/pc/grub-setup.c grub2.new/util/i386/pc/grub-setup.c +--- grub2/util/i386/pc/grub-setup.c 2010-03-22 13:49:13.000000000 +0000 ++++ grub2.new/util/i386/pc/grub-setup.c 2010-03-22 13:53:10.000000000 +0000 +@@ -36,6 +36,7 @@ + #include <grub/util/raid.h> + #include <grub/util/lvm.h> + #include <grub/util/getroot.h> ++#include <grub/util/deviceiter.h> + + static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; + +@@ -646,6 +647,7 @@ + char *core_file = 0; + char *dir = 0; + char *dev_map = 0; ++ struct stat dev_map_stat; + char *root_dev = 0; + char *dest_dev; + int must_embed = 0, force = 0, fs_probe = 1; +@@ -744,6 +746,9 @@ + /* Initialize the emulated biosdisk driver. */ + grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP); + ++ if (stat (dev_map ? : DEFAULT_DEVICE_MAP, &dev_map_stat) == -1) ++ grub_util_iterate_devices (grub_util_biosdisk_probe_device, 0); ++ + /* Initialize all modules. */ + grub_init_all (); + +diff -Nur -x '*.orig' -x '*~' grub2/util/sparc64/ieee1275/grub-setup.c grub2.new/util/sparc64/ieee1275/grub-setup.c +--- grub2/util/sparc64/ieee1275/grub-setup.c 2010-03-22 13:47:27.000000000 +0000 ++++ grub2.new/util/sparc64/ieee1275/grub-setup.c 2010-03-22 13:53:10.000000000 +0000 +@@ -46,6 +46,7 @@ + #include <sys/stat.h> + #include <dirent.h> + #include <grub/util/getroot.h> ++#include <grub/util/deviceiter.h> + + #define _GNU_SOURCE 1 + #include <getopt.h> +@@ -618,6 +619,7 @@ + main (int argc, char *argv[]) + { + struct grub_setup_info ginfo; ++ struct stat dev_map_stat; + + set_program_name (argv[0]); + +@@ -630,6 +632,9 @@ + /* Initialize the emulated biosdisk driver. */ + grub_util_biosdisk_init (ginfo.dev_map ? ginfo.dev_map : DEFAULT_DEVICE_MAP); + ++ if (stat (ginfo.dev_map ? : DEFAULT_DEVICE_MAP, &dev_map_stat) == -1) ++ grub_util_iterate_devices (grub_util_biosdisk_probe_device, 0); ++ + /* Initialize all modules. */ + grub_init_all (); + diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/970_fix_locale_installation.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/970_fix_locale_installation.diff new file mode 100644 index 00000000..ab202885 --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/970_fix_locale_installation.diff @@ -0,0 +1,55 @@ +Description: Copy .mo files from @datadir@/locale + This matches where 'make install' puts them. +Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/2265 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/537998 +Forwarded: http://lists.gnu.org/archive/html/grub-devel/2010-03/msg00074.html +Last-Update: 2010-03-22 + +diff -Nur -x '*.orig' -x '*~' grub2/util/grub-install.in grub2.new/util/grub-install.in +--- grub2/util/grub-install.in 2010-03-22 15:49:32.000000000 +0000 ++++ grub2.new/util/grub-install.in 2010-03-22 15:54:31.000000000 +0000 +@@ -32,6 +32,7 @@ + host_os=@host_os@ + font=@datadir@/@PACKAGE_TARNAME@/ascii.pf2 + pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` ++localedir=@datadir@/locale + + grub_setup=${sbindir}/`echo grub-setup | sed ${transform}` + if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] || [ "${target_cpu}-${platform}" = "mips-yeeloong" ] ; then +@@ -245,9 +246,9 @@ + + # Copy gettext files + mkdir -p ${grubdir}/locale/ +-for file in ${grubdir}/locale/*.mo ${pkglibdir}/locale/*.mo; do +- if test -f "$file"; then +- cp -f "$file" ${grubdir}/locale/ ++for dir in ${localedir}/*; do ++ if test -f "$dir/LC_MESSAGES/grub.mo"; then ++ cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo" + fi + done + +diff -Nur -x '*.orig' -x '*~' grub2/util/i386/efi/grub-install.in grub2.new/util/i386/efi/grub-install.in +--- grub2/util/i386/efi/grub-install.in 2010-03-09 16:14:00.000000000 +0000 ++++ grub2.new/util/i386/efi/grub-install.in 2010-03-22 15:54:31.000000000 +0000 +@@ -31,6 +31,7 @@ + platform=@platform@ + host_os=@host_os@ + pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` ++localedir=@datadir@/locale + + grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` + grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` +@@ -182,9 +183,9 @@ + + # Copy gettext files + mkdir -p ${grubdir}/locale/ +-for file in ${grubdir}/locale/*.mo ${pkglibdir}/locale/*.mo; do +- if test -f "$file"; then +- cp -f "$file" ${grubdir}/locale/ ++for dir in ${localedir}/*; do ++ if test -f "$dir/LC_MESSAGES/grub.mo"; then ++ cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo" + fi + done + diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/971_langpacks.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/971_langpacks.diff new file mode 100644 index 00000000..7e1cb897 --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/971_langpacks.diff @@ -0,0 +1,30 @@ +Description: Prefer translations from language packs +Author: Colin Watson <cjwatson@ubuntu.com> +Bug-Ubuntu: https://bugs.launchpad.net/bugs/537998 +Forwarded: not-needed +Last-Update: 2010-03-22 + +diff -Nur -x '*.orig' -x '*~' grub2/util/grub-install.in grub2.new/util/grub-install.in +--- grub2/util/grub-install.in 2010-03-22 15:58:16.000000000 +0000 ++++ grub2.new/util/grub-install.in 2010-03-22 15:59:04.000000000 +0000 +@@ -246,7 +246,7 @@ + + # Copy gettext files + mkdir -p ${grubdir}/locale/ +-for dir in ${localedir}/*; do ++for dir in ${localedir}/* ${localedir}-langpack/*; do + if test -f "$dir/LC_MESSAGES/grub.mo"; then + cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo" + fi +diff -Nur -x '*.orig' -x '*~' grub2/util/i386/efi/grub-install.in grub2.new/util/i386/efi/grub-install.in +--- grub2/util/i386/efi/grub-install.in 2010-03-22 15:58:16.000000000 +0000 ++++ grub2.new/util/i386/efi/grub-install.in 2010-03-22 15:59:17.000000000 +0000 +@@ -183,7 +183,7 @@ + + # Copy gettext files + mkdir -p ${grubdir}/locale/ +-for dir in ${localedir}/*; do ++for dir in ${localedir}/* ${localedir}-langpack/*; do + if test -f "$dir/LC_MESSAGES/grub.mo"; then + cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo" + fi diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/974_drive_probe.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/974_drive_probe.diff new file mode 100644 index 00000000..0c9f3646 --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/974_drive_probe.diff @@ -0,0 +1,23 @@ +Description: Probe all devices if we've been asked for a drive name + This allows --target=drive to work properly even without a device.map. + . + Depends on 969_lvm_raid_probe.diff. +Author: Colin Watson <cjwatson@ubuntu.com> +Bug-Ubuntu: https://bugs.launchpad.net/bugs/549980 +Forwarded: no +Last-Update: 2010-04-08 + +diff -Nur -x '*.orig' -x '*~' grub2/util/grub-probe.c grub2.new/util/grub-probe.c +--- grub2/util/grub-probe.c 2010-04-08 12:02:36.000000000 +0100 ++++ grub2.new/util/grub-probe.c 2010-04-08 12:04:05.000000000 +0100 +@@ -139,7 +139,9 @@ + } + + if (stat (dev_map, &dev_map_stat) == -1 && +- grub_util_get_dev_abstraction (device_name) != GRUB_DEV_ABSTRACTION_NONE) ++ (print == PRINT_DRIVE || ++ grub_util_get_dev_abstraction (device_name) != ++ GRUB_DEV_ABSTRACTION_NONE)) + { + /* If we don't have a device map, then we won't yet know about the + physical volumes underlying this device, so probe all devices. */ diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/975_hostdisk_hd.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/975_hostdisk_hd.diff new file mode 100644 index 00000000..7ea7f5f8 --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream-1.98/975_hostdisk_hd.diff @@ -0,0 +1,114 @@ +Description: Adjust hostdisk id for hard disks + This allows grub-setup to use its standard workaround for broken BIOSes. +Author: Colin Watson <cjwatson@ubuntu.com> +Bug: http://savannah.gnu.org/bugs/?29464 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/555500 +Forwarded: http://savannah.gnu.org/bugs/?29464 +Last-Update: 2010-04-08 + +diff -Nur -x '*.orig' -x '*~' grub2/util/hostdisk.c grub2.new/util/hostdisk.c +--- grub2/util/hostdisk.c 2010-04-08 17:09:02.000000000 +0100 ++++ grub2.new/util/hostdisk.c 2010-04-08 17:10:18.000000000 +0100 +@@ -186,6 +186,8 @@ + + disk->has_partitions = 1; + disk->id = drive; ++ if (strncmp (map[drive].drive, "hd", 2) == 0) ++ disk->id += 0x80; + disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data)); + data->dev = NULL; + data->access_mode = 0; +@@ -491,9 +493,9 @@ + int is_partition = 0; + char dev[PATH_MAX]; + +- strcpy (dev, map[disk->id].device); ++ strcpy (dev, map[disk->id & 0x7f].device); + if (disk->partition && sector >= disk->partition->start +- && strncmp (map[disk->id].device, "/dev/", 5) == 0) ++ && strncmp (map[disk->id & 0x7f].device, "/dev/", 5) == 0) + is_partition = linux_find_partition (dev, disk->partition->start); + + if (data->dev && strcmp (data->dev, dev) == 0 && +@@ -548,7 +550,7 @@ + } + #endif + +- if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 && ++ if (data->dev && strcmp (data->dev, map[disk->id & 0x7f].device) == 0 && + data->access_mode == (flags & O_ACCMODE)) + { + grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev); +@@ -560,10 +562,10 @@ + if (data->fd != -1) + close (data->fd); + +- fd = open (map[disk->id].device, flags); ++ fd = open (map[disk->id & 0x7f].device, flags); + if (fd >= 0) + { +- data->dev = xstrdup (map[disk->id].device); ++ data->dev = xstrdup (map[disk->id & 0x7f].device); + data->access_mode = (flags & O_ACCMODE); + data->fd = fd; + } +@@ -581,12 +583,12 @@ + #if defined(__APPLE__) + /* If we can't have exclusive access, try shared access */ + if (fd < 0) +- fd = open(map[disk->id].device, flags | O_SHLOCK); ++ fd = open(map[disk->id & 0x7f].device, flags | O_SHLOCK); + #endif + + if (fd < 0) + { +- grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' in open_device()", map[disk->id].device); ++ grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' in open_device()", map[disk->id & 0x7f].device); + return -1; + } + #endif /* ! __linux__ */ +@@ -604,7 +606,7 @@ + offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS; + if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) + { +- grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device); ++ grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id & 0x7f].device); + close (fd); + return -1; + } +@@ -615,7 +617,7 @@ + + if (lseek (fd, offset, SEEK_SET) != offset) + { +- grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device); ++ grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id & 0x7f].device); + close (fd); + return -1; + } +@@ -713,7 +715,7 @@ + parts. -jochen */ + if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) + { +- grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device); ++ grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id & 0x7f].device); + close (fd); + return grub_errno; + } +@@ -725,7 +727,7 @@ + + if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS) + != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) +- grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device); ++ grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id & 0x7f].device); + + return grub_errno; + } +@@ -759,7 +761,7 @@ + + if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS) + != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) +- grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device); ++ grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id & 0x7f].device); + + return grub_errno; + } diff --git a/sys-boot/grub/files/ubuntu-upstream/01_uuids_and_lvm_dont_play_along_nicely.diff b/sys-boot/grub/files/ubuntu-upstream/01_uuids_and_lvm_dont_play_along_nicely.diff new file mode 100644 index 00000000..c997b845 --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream/01_uuids_and_lvm_dont_play_along_nicely.diff @@ -0,0 +1,14 @@ +diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in +index c2da413..cbd9d6b 100644 +--- a/util/grub.d/10_linux.in ++++ b/util/grub.d/10_linux.in +@@ -36,7 +36,8 @@ case ${GRUB_DEVICE} in + esac + + if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ +- || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then ++ || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \ ++ || [ "`grub-probe -t abstraction --device ${GRUB_DEVICE} | sed -e 's,.*\(lvm\).*,\1,'`" = "lvm" ] ; then + LINUX_ROOT_DEVICE=${GRUB_DEVICE} + else + LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} diff --git a/sys-boot/grub/files/ubuntu-upstream/904_disable_floppies.diff b/sys-boot/grub/files/ubuntu-upstream/904_disable_floppies.diff new file mode 100644 index 00000000..66a41cdc --- /dev/null +++ b/sys-boot/grub/files/ubuntu-upstream/904_disable_floppies.diff @@ -0,0 +1,28 @@ + +Author: Robert Millan + +An ugly kludge. Should this be merged upstream? + +Index: util/hostdisk.c +=================================================================== +--- util/hostdisk.c (revision 1832) ++++ util/hostdisk.c (working copy) +@@ -544,6 +544,18 @@ + continue; + } + ++ if (! strncmp (p, "/dev/fd", sizeof ("/dev/fd") - 1)) ++ { ++ char *q = p + sizeof ("/dev/fd") - 1; ++ if (*q >= '0' && *q <= '9') ++ { ++ free (map[drive].drive); ++ map[drive].drive = NULL; ++ grub_util_info ("`%s' looks like a floppy drive, skipping", p); ++ continue; ++ } ++ } ++ + #ifdef __linux__ + /* On Linux, the devfs uses symbolic links horribly, and that + confuses the interface very much, so use realpath to expand |