qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] reading files from qcow2-formated image disk for wi


From: 马磊
Subject: [Qemu-devel] [PATCH] reading files from qcow2-formated image disk for windows system
Date: Wed, 9 Jan 2013 15:31:50 +0800



Hi,
    The final effect is as follows:
    
address@hidden Fri Dec 28 ~/honeypot/xen/xen-4.1.2]$ qemu-img-xen cat -f /1/boot.ini ~/vm-check.img 
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect

address@hidden Fri Dec 28 ~/honeypot/xen/xen-4.1.2]$ qemu-img-xen ls -l -d /1/ ~/vm-check.img 
【name                 size(bytes) dir?      date                create-time】
AUTOEXEC.BAT 0                file 2010-12-22        17:30:37
boot.ini               211                file 2010-12-23        01:24:41
bootfont.bin  322730                file 2004-11-23        20:00:00



As you see above, the patch add two sub-commands for qemu-img-xen:cat and ls.

For details in the patch, please check the attachment. 



Does anyone prefer this feature?!



Signed-off-by: Lei Ma (address@hidden)

diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/debug.c xen-4.1.2-b/tools/ioemu-qemu-xen/debug.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/debug.c 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/debug.c 2012-12-28 16:02:40.999933925 +0800
@@ -0,0 +1,182 @@
+#include<time.h>
+#include<sys/stat.h>
+#include<stdarg.h>
+#include<fcntl.h>
+#include"debug.h"
+#include <unistd.h>
+#include <string.h>
+
+#define KB(x)    ((x)*1024)
+
+static int dbg_term = 0, dbg_file = 0, log_day = 0;
+static FILE* fp_log = NULL;
+static char dir[128]={0,}, filename[160];
+static void init_file_path(void);
+static char printbuf[1024]={};
+int mkdir_recursive(char* path);
+
+
+void print_error(char* file, char* function, int line, const char *fmt, ...)
+{
+  va_list args;
+  int i;
+
+  if( !dbg_term && !dbg_file )
+    return;
+
+  va_start(args, fmt);
+  i=vsprintf( printbuf, fmt, args );
+  printbuf[i] = 0;
+  va_end(args);
+
+  if( dbg_term )
+    {
+      printf("[%s]%s(%d):\n%s\n", file, function, line, printbuf);
+    }
+
+  if( dbg_file )
+    {
+      time_t t = time( NULL );
+      struct tm* tm1 = localtime(&t);
+      if( !tm1 ) return;
+      //if( tm1->tm_mday != log_day )
+      {
+ //init_file_path();
+      }
+      char tmp[16];
+      strftime( tmp, 15, "%X", tm1 );
+      fprintf( fp_log, "%s [%s]%s(%d): %s\n", tmp, file, function, line, printbuf);
+      fflush( fp_log );
+    }
+}
+
+static char* hex_str(unsigned char *buf, int len, char* outstr )
+{
+
+  const char *set = "0123456789abcdef";
+  char *tmp;
+  unsigned char *end;
+  if (len > 1024)
+    len = 1024;
+  end = buf + len;
+  tmp = &outstr[0];
+  while (buf < end)
+    {
+      *tmp++ = set[ (*buf) >> 4 ];
+      *tmp++ = set[ (*buf) & 0xF ];
+      *tmp++ = ' ';
+      buf ++;
+    }
+  *tmp = '\0';
+  return outstr;
+}
+
+void hex_dump( unsigned char * buf, int len )
+{
+  char str[KB(4)];
+  if( dbg_term )
+    puts( hex_str( buf, len, str ) );
+  if( dbg_file ){
+    fputs( hex_str( buf, len, str ), fp_log );
+    fprintf( fp_log, "\n" );
+    fflush( fp_log );
+  }
+  //fprintf( stderr, hex_str( buf, len ) );
+}
+
+void debug_term_on()
+{
+  dbg_term = 1;
+}
+
+void debug_term_off()
+{
+  dbg_term = 0;
+}
+
+
+int mkdir_recursive( char* path )
+{
+  char *p;
+
+  if( access( path, 0 ) == 0 )
+    return 0;
+
+  for( p=path; *p; p++ )
+    {
+      if( p>path && *p == '/' )
+ {
+   *p = 0;
+   if( access( path, 0 ) != 0 )
+     {
+#ifdef __WIN32__
+       mkdir( path );
+#else
+       if( mkdir( path, S_IRWXU ) != 0 )
+ return -1;
+#endif
+     }
+   *p = '/';
+ }
+    }
+#ifdef __WIN32__
+  return mkdir( path );
+#else
+  return mkdir( path, S_IRWXU );
+#endif
+}
+
+void init_file_path()
+{
+  char tmp[64];
+  time_t t = time( NULL );
+  struct tm* tm1 = localtime(&t);
+  
+  if( !tm1 )
+    {
+      perror("debug.c init_file_path: ERROR GETTING SYSTEM TIME.");
+    }
+  log_day = tm1->tm_mday;
+  strftime( tmp, 64, "/%Y-%m-%d.txt", tm1 );
+  
+  if( access( dir, 0 )!=0 )
+    {
+      (mkdir_recursive( dir )<0) ? perror("mkdir_recursive fail!!\n") : 0;
+    }
+  strcpy( filename, dir );
+  strcat( filename, tmp );
+  if( fp_log )
+    fclose( fp_log );
+  fp_log = fopen( filename, "w" );
+  if(fp_log)
+    {
+      fprintf(fp_log,"======================LOG  START========================\n");
+      fclose(fp_log);  fp_log=NULL;
+      fp_log = fopen( filename, "a+" );
+      NULL==fp_log ? printf("init_file_path():fopen(a+) fail\n") : 0;
+    }
+}
+
+void debug_file_on(char *path)
+{
+  if( dbg_file )
+    return;
+  debug_set_dir(path);
+  init_file_path();
+  dbg_file = 1;
+}
+
+void debug_file_off()
+{
+  if( !dbg_file )
+    return;
+  dbg_file = 0;
+  if( fp_log )
+    fclose( fp_log );
+}
+
+void debug_set_dir(char* str)
+{
+  strcpy( dir, str );
+}
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/debug.h xen-4.1.2-b/tools/ioemu-qemu-xen/debug.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/debug.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/debug.h 2012-12-28 16:02:41.000934327 +0800
@@ -0,0 +1,34 @@
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+
+//#define RELEASE
+
+#ifndef RELEASE
+#define DBG(args ...) \
+  print_error( (char*)__FILE__, (char*)__func__, __LINE__, ##args )
+#else
+#define DBG(args ...)   \
+  do   \
+    {                                               \
+fprintf(logfile,"%s::[%s]::(%d):\n",                \
+ (char*)__FILE__, (char*)__func__, __LINE__);      \
+fprintf(logfile, ##args); fprintf(logfile, "\n");   \
+}                                                    \
+while(0)
+//#define DBG printf
+#endif
+#define MSGprintf
+void print_error(char* file, char* function, int line, const char *fmt, ...);
+void hex_dump( unsigned char * buf, int len );
+void debug_term_on(void);
+void debug_term_off(void);
+void debug_file_on(char *path);
+void debug_file_off(void);
+void debug_set_dir(char* str);
+
+#endif //_DEBUG_H
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fat.c xen-4.1.2-b/tools/ioemu-qemu-xen/fat.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/fat.c 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/fat.c 2012-12-28 16:02:41.001934709 +0800
@@ -0,0 +1,936 @@
+/* fat.c - FAT filesystem */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "misc.h"
+#include "fat.h"
+#include "debug.h"
+
+
+int g_err = GRUB_ERR_NONE;
+int64_t s_bpb_bytes_per_sector;
+int64_t s_part_off_sector;
+
+static int bdrv_pread_from_sector_of_volume(BlockDriverState *bs, int64_t offset,
+               void *buf1, int count1)
+{
+  int64_t off = s_bpb_bytes_per_sector * s_part_off_sector + offset;
+  return bdrv_pread(bs, off, buf1, count1);
+}
+
+
+static int
+fat_log2 (unsigned x)
+{
+  int i;
+
+  if (x == 0)
+    return -1;
+
+  for (i = 0; (x & 1) == 0; i++)
+    x >>= 1;
+
+  if (x != 1)
+    return -1;
+
+  return i;
+}
+
+
+char *
+grub_fat_find_dir (BlockDriverState *bs, struct grub_fat_data *data,
+    const char *path,
+    int (*hook) (const char *filename,
+ const struct grub_dirhook_info *info,
+ void *closure),
+    void *closure);
+
+
+
+struct grub_fat_data *
+grub_fat_mount (BlockDriverState *bs, uint32_t part_off_sector)
+{
+  struct grub_fat_bpb bpb;
+  struct grub_fat_data *data = "">
+  grub_uint32_t first_fat, magic;
+  int64_t off_bytes = (int64_t)part_off_sector << GRUB_DISK_SECTOR_BITS;
+
+  if (! bs)
+    goto fail;
+
+  data = "" grub_fat_data *) malloc (sizeof (*data));
+  if (! data)
+    goto fail;
+
+  /* Read the BPB.  */
+  if (bdrv_pread(bs, off_bytes, &bpb, sizeof(bpb)) != sizeof(bpb))
+    {
+      DBG("bdrv_pread fail....");
+      goto fail;
+    }
+    
+  if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype,
+    "FAT12", 5)
+      && grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype,
+       "FAT16", 5)
+      && grub_strncmp((const char *) bpb.version_specific.fat32.fstype,
+       "FAT32", 5)
+      )
+    {
+      
+      DBG("fail here-->grub_strncmp......");
+      goto fail;
+    }
+
+  /* Get the sizes of logical sectors and clusters.  */
+  s_bpb_bytes_per_sector = (bpb.bytes_per_sector);
+  s_part_off_sector = part_off_sector;
+  data->logical_sector_bits =
+    fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector));
+  DBG("bpb.bytes_per_sector=0x%x, le_to_cpu16=0x%x",
+  bpb.bytes_per_sector, grub_le_to_cpu16 (bpb.bytes_per_sector));
+  
+
+  if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS)
+  {
+    DBG("fail here-->logical_sector_bits"); 
+    goto fail;
+  }
+  data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
+
+  DBG("bpb.sectors_per_cluster=%u", bpb.sectors_per_cluster);
+  data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
+  if (data->cluster_bits < 0)
+    {
+      DBG("fail here-->cluster_bits......line[%u]", __LINE__); 
+      goto fail;
+    }
+  data->cluster_bits += data->logical_sector_bits;
+
+  /* Get information about FATs.  */
+  DBG("bpb.num_reserved_sectors=%u,"
+      "le_to_cpu16=%u",
+      bpb.num_reserved_sectors,
+      grub_le_to_cpu16 (bpb.num_reserved_sectors));
+  data->fat_sector = (grub_le_to_cpu16 (bpb.num_reserved_sectors)
+       << data->logical_sector_bits);
+  DBG("data->fat_sector=%u, part_off_sector=%u",
+      data->fat_sector, part_off_sector);
+  if (data->fat_sector == 0)
+    {
+      DBG("fail here-->fat_sector......"); 
+      goto fail;
+    }
+  data->sectors_per_fat = ((bpb.sectors_per_fat_16
+     ? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
+     : grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32))
+    << data->logical_sector_bits);
+  DBG("bpb.version_specific.fat32.sectors_per_fat_32=%u\n"
+  "grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32)=%u",
+  bpb.version_specific.fat32.sectors_per_fat_32,
+  grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32));
+  if (data->sectors_per_fat == 0)
+    goto fail;
+
+  /* Get the number of sectors in this volume.  */
+  data->num_sectors = ((bpb.num_total_sectors_16
+ ? grub_le_to_cpu16 (bpb.num_total_sectors_16)
+ : grub_le_to_cpu32 (bpb.num_total_sectors_32))
+        << data->logical_sector_bits);
+  if (data->num_sectors == 0)
+    {
+      DBG("fail here-->num_sectors......"); 
+      goto fail;
+    }
+  /* Get information about the root directory.  */
+  if (bpb.num_fats == 0)
+    {
+      DBG("fail here-->num_fats......"); 
+      goto fail;
+    }
+  data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
+  data->num_root_sectors
+    = ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries)
+  * GRUB_FAT_DIR_ENTRY_SIZE
+  + grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
+ >> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
+       << (data->logical_sector_bits));
+  //in fat32 : root is not included in file cluster??
+  data->cluster_sector = data->root_sector + data->num_root_sectors;
+  data->num_clusters = (((data->num_sectors - data->cluster_sector)
+  >> (data->cluster_bits + data->logical_sector_bits))
+ + 2);
+
+  if (data->num_clusters <= 2)
+    {
+      DBG("fail here-->num_clusters......"); 
+      goto fail;
+    }
+  if (! bpb.sectors_per_fat_16)
+    {
+      /* FAT32.  */
+      grub_uint16_t flags = grub_le_to_cpu16 (bpb.version_specific.fat32.extended_flags);
+
+      data->root_cluster = grub_le_to_cpu32 (bpb.version_specific.fat32.root_cluster);
+      data->fat_size = 32;
+      data->cluster_eof_mark = 0x0ffffff8;
+
+      if (flags & 0x80)
+ {
+   /* Get an active FAT.  */
+   unsigned active_fat = flags & 0xf;
+
+   if (active_fat > bpb.num_fats)
+     goto fail;
+
+   data->fat_sector += active_fat * data->sectors_per_fat;
+ }
+
+      if (bpb.num_root_entries != 0 || bpb.version_specific.fat32.fs_version != 0)
+ goto fail;
+    }
+  else
+    {
+      /* FAT12 or FAT16.  */
+      data->root_cluster = ~0U;
+
+      if (data->num_clusters <= 4085 + 2)
+ {
+   /* FAT12.  */
+   data->fat_size = 12;
+   data->cluster_eof_mark = 0x0ff8;
+ }
+      else
+ {
+   /* FAT16.  */
+   data->fat_size = 16;
+   data->cluster_eof_mark = 0xfff8;
+ }
+    }
+
+  /* More sanity checks.  */
+  if (data->num_sectors <= data->fat_sector)
+    goto fail;
+
+  
+  DBG("data->fat_sector=%u, data->sectors_per_fat=%u",
+  data->fat_sector, data->sectors_per_fat);
+  if (bdrv_pread_from_sector_of_volume(bs,
+  data->fat_sector << GRUB_DISK_SECTOR_BITS,
+  &first_fat,
+  sizeof (first_fat)) != sizeof(first_fat))
+    {
+      DBG("fail here-->bdrv_pread......"); 
+      goto fail;
+    }
+
+  first_fat = grub_le_to_cpu32 (first_fat);
+
+  if (data->fat_size == 32)
+    {
+      first_fat &= 0x0fffffff;
+      magic = 0x0fffff00;
+    }
+  else if (data->fat_size == 16)
+    {
+      first_fat &= 0x0000ffff;
+      magic = 0xff00;
+    }
+  else
+    {
+      first_fat &= 0x00000fff;
+      magic = 0x0f00;
+    }
+
+  /* Serial number.  */
+  if (bpb.sectors_per_fat_16)
+    data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
+  else
+    data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
+
+  /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
+     descriptor, even if it is a so-called superfloppy (e.g. an USB key).
+     The check may be too strict for this kind of stupid BIOSes, as
+     they overwrite the media descriptor.  */
+  if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
+    {
+      DBG("fail here-->first_fat=0x%x, magic=0x%x",
+      first_fat, magic); 
+      goto fail;
+    }
+  /* Start from the root directory.  */
+  data->file_cluster = data->root_cluster;
+  data->cur_cluster_num = ~0U;
+  data->attr = GRUB_FAT_ATTR_DIRECTORY;
+  DBG("data->file_cluster=%u \ndata->cur_cluster_num=%u \ndata->attr=0x%x\n"
+  "data->logical_sector_bits=%u\n"
+  "data->cluster_bits=%u",
+  data->file_cluster, data->cur_cluster_num, data->attr,
+  data->logical_sector_bits, data->cluster_bits);
+  return data;
+
+ fail:
+
+  free (data);
+  printf("not a FAT filesystem!\n");
+  return 0;
+}
+
+
+
+//从文件的指定偏移offset字节处读取len字节的数据到buf
+//文件由data->file_cluster指定
+//data->file_cluster指定了文件的起始簇号
+//默认data->file_cluster=2,代表根目录
+static grub_ssize_t
+grub_fat_read_data (BlockDriverState *bs, struct grub_fat_data *data,
+     void (*read_hook) (grub_disk_addr_t sector,
+        unsigned offset, unsigned length,
+        void *closure),
+     void *closure,
+     grub_off_t offset, grub_size_t len, char *buf)
+{
+  grub_size_t size;
+  grub_uint32_t logical_cluster;
+  unsigned logical_cluster_bits;
+  grub_ssize_t ret = 0;
+  unsigned long sector;
+  uint64_t off_bytes = 0; 
+  /* This is a special case. FAT12 and FAT16 doesn't have the root directory
+     in clusters.  */
+  if (data->file_cluster == ~0U)
+    {
+      size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
+      if (size > len)
+ size = len;
+
+      off_bytes = ((uint64_t)data->root_sector << GRUB_DISK_SECTOR_BITS) + offset;
+      if(bdrv_pread_from_sector_of_volume(bs, off_bytes, buf, size ) != size) 
+ return -1;
+
+      return size;
+    }
+
+  /* Calculate the logical cluster number and offset.  */
+  logical_cluster_bits = (data->cluster_bits
+   + data->logical_sector_bits
+   + GRUB_DISK_SECTOR_BITS);
+  logical_cluster = offset >> logical_cluster_bits;    //which cluster to read 
+  offset &= (1 << logical_cluster_bits) - 1;           //mod
+
+  if (logical_cluster < data->cur_cluster_num)   //
+    {
+      data->cur_cluster_num = 0;
+      data->cur_cluster = data->file_cluster; // 第2个fat表项开始记录目录和文件
+    }
+
+  while (len)
+    {
+      while (logical_cluster > data->cur_cluster_num)
+ {
+   /* Find next cluster.  */
+   grub_uint32_t next_cluster;
+   unsigned long fat_offset;
+
+   switch (data->fat_size)
+     {
+     case 32:
+       fat_offset = data->cur_cluster << 2;
+       break;
+     case 16:
+       fat_offset = data->cur_cluster << 1;
+       break;
+     default:
+       /* case 12: */
+       fat_offset = data->cur_cluster + (data->cur_cluster >> 1);
+       break;
+     }
+
+   /* Read the FAT.  */
+   int len = (data->fat_size + 7) >> 3;
+   uint64_t off_bytes =  ((uint64_t)data->fat_sector << GRUB_DISK_SECTOR_BITS) + fat_offset; 
+   if (bdrv_pread_from_sector_of_volume (bs, off_bytes, 
+   (char *) &next_cluster, 
+   len) != len)   //从fat表读取簇号
+     return -1;
+
+   next_cluster = grub_le_to_cpu32 (next_cluster);
+   switch (data->fat_size)
+     {
+     case 16:
+       next_cluster &= 0xFFFF;
+       break;
+     case 12:
+       if (data->cur_cluster & 1)
+ next_cluster >>= 4;
+
+       next_cluster &= 0x0FFF;
+       break;
+     }
+
+   DBG ("fat_size=%d, next_cluster=%u",
+ data->fat_size, next_cluster);
+
+   /* Check the end.  */
+   if (next_cluster >= data->cluster_eof_mark)
+     return ret;
+
+   if (next_cluster < 2 || next_cluster >= data->num_clusters)
+     {
+       DBG("invalid cluster %u................",
+   next_cluster);
+       return -1;
+     }
+
+   data->cur_cluster = next_cluster;
+   data->cur_cluster_num++;
+ }
+
+      /* Read the data here.  */
+      //逻辑簇所对应的绝对扇区
+      sector = (data->cluster_sector
+ + ((data->cur_cluster - 2)
+    << (data->cluster_bits + data->logical_sector_bits))); 
+      //绝对扇区中去掉偏移后的字节数
+      size = (1 << logical_cluster_bits) - offset;
+      if (size > len)
+ size = len;
+
+      //disk->read_hook = read_hook;
+      //disk->closure = closure;
+      int64_t off_bytes = ((uint64_t)sector << GRUB_DISK_SECTOR_BITS) + offset;
+      //disk->read_hook = 0;
+      if (bdrv_pread_from_sector_of_volume (bs, off_bytes, buf, size) != size)
+ return -1;
+
+      len -= size;
+      buf += size;
+      ret += size;
+      logical_cluster++;
+      offset = 0;  //以后读的都是完整扇区
+    }
+
+  return ret;
+}
+
+//遍历由data->file_cluster指定的目录
+static int
+grub_fat_iterate_dir (BlockDriverState *bs, struct grub_fat_data *data,
+       int (*hook) (const char *filename,
+    struct grub_fat_dir_entry *dir,
+    void *closure),
+       void *closure)
+{
+  struct grub_fat_dir_entry dir;
+  char *filename, *filep = 0;
+  grub_uint16_t *unibuf;
+  int slot = -1, slots = -1;
+  int checksum = -1;
+  grub_ssize_t offset = -sizeof(dir);
+
+  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
+    return printf("not a directory......\n");
+
+  /* Allocate space enough to hold a long name.  */
+  filename = (char*)malloc (0x40 * 13 * 4 + 1);
+  unibuf = (grub_uint16_t *) malloc (0x40 * 13 * 2);
+  char *gbname = (char*)malloc(0x40 * 13 * 2);
+  if (! filename || ! unibuf || !gbname)
+    {
+      free(gbname);
+      free (filename);
+      free (unibuf);
+      perror("iterate: malloc failed!...\n");
+      return -1;
+    }
+
+  
+  int count = 0;
+  while (1)
+    {
+      unsigned i;
+
+      /* Adjust the offset.  */
+      offset += sizeof (dir);
+      DBG("\n[%d]offset=%u,"
+      "data->cur_cluster_num=%u,data->cur_cluster=%u", 
+      count+1, offset, 
+      data->cur_cluster_num, data->cur_cluster);
+      /* Read a directory entry.  */
+      //0x0表示空目录
+      if ((grub_fat_read_data (bs, data, 0, 0,
+        offset, sizeof (dir), (char *) &dir)
+    != sizeof (dir) || dir.name[0] == 0))
+ {
+   DBG("break...dir.name[0]==%d", dir.name[0]);
+   break;
+ }
+      /* Handle long name entries.  */
+      if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
+ {
+   DBG("long name...");
+   struct grub_fat_long_name_entry *long_name
+     = (struct grub_fat_long_name_entry *) &dir;
+   grub_uint8_t id = long_name->id;
+
+   if (id & 0x40)  //the last item
+     {
+       id &= 0x3f;   //index or ordinal number  1~31
+       slots = slot = id;
+       checksum = long_name->checksum;
+       DBG("the last ordinal num=%d!!!", id);
+     }
+
+   if (id != slot || slot == 0 || checksum != long_name->checksum)
+     {
+       DBG("not valid ordinal number ,ignore...continue");
+       checksum = -1;
+       continue;
+     }
+
+   slot--;
+   memcpy (unibuf + slot * 13, long_name->name1, 5 * 2);
+   memcpy (unibuf + slot * 13 + 5, long_name->name2, 6 * 2);
+   memcpy (unibuf + slot * 13 + 11, long_name->name3, 2 * 2);
+   DBG("memcpy...continue");
+   continue;
+ }
+
+      
+      /* Check if this entry is valid.  */
+      //oxe5表示已经被删除
+      if (dir.name[0] == 0xe5 || (dir.attr & ~GRUB_FAT_ATTR_VALID))
+ {
+   DBG("dir.name[0]=0x%x, dir.attr=0x%x not valid...continue", 
+  dir.name[0], dir.attr);
+   continue;
+ }
+
+      DBG("checksum=%d, slot=%d", checksum, slot);
+      /* This is a workaround for Japanese.  */
+      if (dir.name[0] == 0x05)
+ dir.name[0] = 0xe5;
+
+      if (checksum != -1 && slot == 0)
+ {
+   DBG("checksuming");
+   grub_uint8_t sum;
+
+   for (sum = 0, i = 0; i < sizeof (dir.name); i++)
+     sum = ((sum >> 1) | (sum << 7)) + dir.name[i];
+
+   if (sum == checksum)
+     {//长名表项后面紧接短名表项,验证成功则证明真正是长名字
+       int u;
+
+       for (u = 0; u < slots * 13; u++)
+ unibuf[u] = grub_le_to_cpu16 (unibuf[u]);
+
+       *grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
+    slots * 13) = '\0';
+
+       
+       checksum = -1;
+       for (i = 0; i < sizeof (dir.name); i++)
+ DBG("0x%x  ", dir.name[i]);
+       
+       u2g(filename, strlen(filename), gbname, 0x40 * 13 * 2);
+       DBG("\ndir.name=%s, filename=%s, dir.attr=0x%x,"
+      "sum==checksum...continue",
+      dir.name, gbname, dir.attr);
+       
+       count++;
+       
+       if (hook && hook (gbname, &dir, closure))
+         break;
+       
+       continue;
+     }
+
+   checksum = -1;
+ }
+
+      //后面的处理针对非真实长名和真实短名
+      /* Convert the 8.3 file name.  */
+      //去掉短名的空格,全改为小写
+      filep = filename;
+      if (dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
+ {
+   DBG("VOLUME");
+   for (i = 0; i < sizeof (dir.name) && dir.name[i]
+  && ! grub_isspace (dir.name[i]); i++)
+     *filep++ = dir.name[i];
+ }
+      else
+ {
+   for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
+     *filep++ = grub_tolower (dir.name[i]);
+
+   *filep = '.';
+
+   for (i = 8; i < 11 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
+     *++filep = grub_tolower (dir.name[i]);
+
+   if (*filep != '.')
+     filep++;
+ }
+      *filep = '\0';
+      
+      //for (i = 0; i < sizeof (dir.name); i++)
+      // DBG("0x%x  ", dir.name[i]);
+      DBG("\ndir.name=%s, filename=【%s】, dir.attr=0x%x,"
+      "...next while",
+      dir.name, filename, dir.attr);
+      count++;
+      /*if(strcmp(filename, ".") && strcmp(filename, ".."))
+ {
+   DBG("{==============>");
+   struct grub_fat_data *data2 = NULL;
+   data2 = (struct grub_fat_data*)malloc(sizeof(*data));
+   memcpy(data2, data, sizeof(*data));
+   data2->attr = dir.attr;
+   data2->file_size = grub_le_to_cpu32 (dir.file_size);
+   data2->file_cluster = ((grub_le_to_cpu16 (dir.first_cluster_high) << 16)
+  | grub_le_to_cpu16 (dir.first_cluster_low));
+   data2->cur_cluster_num = ~0U;
+   (grub_fat_iterate_dir(bs, data2, NULL, NULL) < 0) ? DBG("error !!!!!!") : 0;
+   free(data2);
+   DBG("<===================}");
+ }
+      */
+      if (hook && hook (filename, &dir, closure))
+        break;
+    }
+
+  free(gbname);
+  free (filename);
+  free (unibuf);
+
+  return 0;
+}
+
+
+
+//传给grub_fat_find_hook的参数closure
+struct grub_fat_find_dir_closure
+{
+  struct grub_fat_data *data;
+  int (*hook) (const char *filename,
+        const struct grub_dirhook_info *info,
+        void *closure);
+  void *closure;
+  char *dirname;
+  int call_hook;
+  int found;
+};
+
+
+static int
+grub_fat_find_dir_hook (const char *filename, struct grub_fat_dir_entry *dir,
+ void *closure)
+{
+  struct grub_fat_find_dir_closure *c = closure;
+  struct grub_dirhook_info info;
+  memset (&info, 0, sizeof (info));
+
+  info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY);
+  info.case_insensitive = 1;
+  info.mtimeset = (dir->c_date || dir->c_time);
+  info.mtime = (((grub_uint32_t)dir->c_date << 16) | (dir->c_time));
+  info.filesize = dir->file_size;
+  
+  DBG("target file 【%s】======", c->dirname);
+  if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
+    {
+      DBG("volume id , ignore======");
+      return 0;
+    }
+  
+  if (*(c->dirname) == '\0' && (c->call_hook))
+    { //打开的是目录  /x/path1/path2/
+      //返回0,让iterate时只是打印信息,而不退出while
+      c->found = 1;
+      if(!(c->data->attr & GRUB_FAT_ATTR_DIRECTORY))
+ {
+   printf("it's not a directory!\n");
+ }
+      DBG("list the dir 【%s】===========",
+   ((struct ls_ctrl*)c->closure)->dirname);
+      return c->hook (filename, &info, c->closure);
+    }
+
+  
+  if (grub_strcasecmp (c->dirname, filename) == 0)
+    { //打开的是文件 /x/path1/file
+      DBG("found======");
+      struct grub_fat_data *data = "">
+
+      c->found = 1;
+      data->attr = dir->attr;
+      data->file_size = grub_le_to_cpu32 (dir->file_size);
+      data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16)
+        | grub_le_to_cpu16 (dir->first_cluster_low));
+      data->cur_cluster_num = ~0U;
+
+      if (c->call_hook)
+ c->hook (filename, &info, c->closure);
+
+      return 1;
+    }
+  else
+    {
+      DBG("not match======");
+    }
+  return 0;
+}
+
+
+/* Find the underlying directory or file in PATH and return the
+   next path. If there is no next path or an error occurs, return NULL.
+   If HOOK is specified, call it with each file name.  */
+//在由data指定的目录下查找由path路径指定的文件夹或文件
+//找到之后交由 grub_fat_find_dir_hook函数处理,其中closure参数是关键
+char *
+grub_fat_find_dir (BlockDriverState *bs, struct grub_fat_data *data,
+    const char *path,
+    int (*hook) (const char *filename,
+ const struct grub_dirhook_info *info,
+ void *closure),
+    void *closure)
+{
+  char *dirname, *dirp;
+  struct grub_fat_find_dir_closure c;
+  DBG("to search [%s]...in data->attr=0x%x", path, data->attr);
+  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
+    {
+      printf("not a directory...........\n");
+      return 0;
+    }
+
+  /* Extract a directory name.  */
+  while (*path == '/')
+    path++;
+
+  dirp = grub_strchr (path, '/');
+  if (dirp)
+    {
+      unsigned len = dirp - path;
+
+      dirname = (char*)malloc (len + 1);
+      if (! dirname)
+ return 0;
+
+      memcpy (dirname, path, len);
+      dirname[len] = '\0';
+    }
+  else
+    {
+    /* This is actually a file.  */
+      dirname = grub_strdup (path);
+    }
+  DBG("searching \"%s\"======", dirname);
+  c.data = "">
+  c.hook = hook;
+  c.closure = closure;
+  c.dirname =dirname;
+  c.found = 0;
+  c.call_hook = (! dirp && hook);  //针对目录的hook
+  
+  int ret = grub_fat_iterate_dir (bs, data, grub_fat_find_dir_hook, &c);
+  if(0 == ret && !c.found)
+    {
+      g_err = GRUB_ERR_NOT_FOUND; 
+      printf("file not found..\n");
+    }
+  else if(ret < 0)
+    {
+      g_err = GRUB_ERR_UNKNOWN;
+      printf("iterate error!\n");
+    }
+    
+  
+  free (dirname);
+
+  return (c.found && 0==ret) ? dirp : 0;
+}
+
+
+
+
+
+grub_err_t
+grub_fat_open (grub_file_t file, const char *name)
+{
+  struct grub_fat_data *data = "">
+  char *p = (char *) name;
+
+  
+  data = "" (file->bs, file->part_off_sector);
+  if (! data)
+    {
+      printf("[%s]: mount error!\n", name);
+      goto fail;
+    }
+
+  int i = 0;
+  do
+    {
+      p = grub_fat_find_dir (file->bs, data, p, 0, 0);
+      DBG("%d cycle past【path=%s】.......", i+1, p);
+      //error judge......
+    }
+  while (p);
+
+  DBG("exit while======");
+  if ((GRUB_ERR_NONE == g_err) 
+      && (data->attr & GRUB_FAT_ATTR_DIRECTORY))
+    {
+      printf ("[%s]: not a file!\n", name);
+      goto fail;
+    }
+  
+  if(GRUB_ERR_NONE == g_err)
+    {
+      DBG("found======");
+    }
+  else
+    {
+      printf("not found or error!\n");
+      goto fail;
+    }
+
+  DBG("11111111111111111111111");
+  file->data = "">
+  file->size = data->file_size;
+  return 0;
+
+ fail:
+  free(data); 
+  file->data = "">
+  DBG("2222222222222222222222");
+  return 1;
+}
+
+
+#define    TIME_BIT    0xFFFF
+#define    TIME_HOUR_BIT    0xF800
+#define    TIME_MINUTE_BIT    0x07E0
+#define    TIME_SECOND_BIT    0x001F
+#define    DATE_BIT    0xFFFF0000
+#define    DATE_YEAR_BIT    0xFE00
+#define    DATE_MONTH_BIT    0x01E0
+#define    DATE_DAY_BIT    0x001F
+static  int find_then_ls_hook(const char *filename,
+    const struct grub_dirhook_info *info, void *closure)
+{
+  struct ls_ctrl* ctrl = (struct ls_ctrl*)closure;
+  DBG("detail=%d", ctrl->detail);
+  printf("%s", filename);
+  if(!ctrl->detail)
+    {
+      printf("\n");
+      return 0;
+    }
+  else
+    {
+      printf("\t");
+    }
+
+
+  printf("%ubytes\t", (info->filesize));
+  printf("%s\t", (info->dir ? "dir" : "file"));
+  grub_uint16_t time = ((info->mtime) & TIME_BIT);
+  grub_uint16_t date = ((info->mtime) & DATE_BIT) >> 16;
+  
+  printf("%04d/%02d/%02d\t",
+  ((date & DATE_YEAR_BIT) >> 9) + 1980,
+  (date & DATE_MONTH_BIT) >> 5,
+  (date & DATE_DAY_BIT));
+  printf("%02d:%02d:%02d\n", 
+  (time & TIME_HOUR_BIT) >> 11,
+  (time & TIME_MINUTE_BIT) >> 5,
+  time & TIME_SECOND_BIT) * 2;  
+  
+  return 0;  // 最终返回给iterate
+}
+
+
+grub_err_t
+grub_fat_ls (grub_file_t file, const char *path,
+       int (*hook) (const char *filename,
+    const struct grub_dirhook_info *info, void *closure),
+       void *closure)
+{
+  struct grub_fat_data *data = "">
+  grub_size_t len;
+  char *dirname = 0;
+  char *p;
+  
+  data = "" (file->bs, file->part_off_sector);
+  if (! data)
+    goto fail;
+
+  file->data = "">
+  /* Make sure that DIRNAME terminates with '/'.  */
+  len = strlen(path);
+  dirname = (char*)malloc (len + 1 + 1);
+  if (! dirname)
+    goto fail;
+  memcpy (dirname, path, len);
+  p = dirname + len;
+  if (path[len - 1] != '/')
+    *p++ = '/';
+  *p = '\0';
+  p = dirname;
+
+  do
+    {
+      p = grub_fat_find_dir (file->bs, data, p, find_then_ls_hook, closure);
+    }
+  while (p && g_err == GRUB_ERR_NONE);
+
+  
+
+ fail:
+
+  free (dirname);
+  free (data);  file->data = "">
+  
+  return g_err;
+}
+
+
+grub_err_t grub_fat_close(grub_file_t file)
+{
+  free(file->data);
+  return g_err;
+}
+
+
+grub_ssize_t grub_fat_read(grub_file_t file, grub_off_t offset,
+    grub_size_t len, char *buf)
+{
+  return grub_fat_read_data(file->bs, file->data, NULL, NULL, offset, len, buf);
+}
+
+
+
+
+
+
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fat.h xen-4.1.2-b/tools/ioemu-qemu-xen/fat.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/fat.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/fat.h 2012-12-28 16:02:41.002938019 +0800
@@ -0,0 +1,160 @@
+#ifndef FS_FAT_H
+#define FS_FAT_H
+
+
+#include "fs-types.h"
+#include "block_int.h"
+#include "fs-comm.h"
+#include "grub_err.h"
+
+
+#define GRUB_DISK_SECTOR_BITS      9
+#define GRUB_FAT_DIR_ENTRY_SIZE 32
+
+#define GRUB_FAT_ATTR_READ_ONLY 0x01
+#define GRUB_FAT_ATTR_HIDDEN 0x02
+#define GRUB_FAT_ATTR_SYSTEM 0x04
+#define GRUB_FAT_ATTR_VOLUME_ID 0x08
+#define GRUB_FAT_ATTR_DIRECTORY 0x10
+#define GRUB_FAT_ATTR_ARCHIVE 0x20
+
+#define GRUB_FAT_MAXFILE 256
+
+#define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \
+  | GRUB_FAT_ATTR_HIDDEN \
+  | GRUB_FAT_ATTR_SYSTEM \
+  | GRUB_FAT_ATTR_VOLUME_ID)
+#define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \
+  | GRUB_FAT_ATTR_HIDDEN \
+  | GRUB_FAT_ATTR_SYSTEM \
+  | GRUB_FAT_ATTR_DIRECTORY \
+  | GRUB_FAT_ATTR_ARCHIVE \
+  | GRUB_FAT_ATTR_VOLUME_ID)
+
+struct grub_fat_bpb
+{
+  grub_uint8_t jmp_boot[3];
+  grub_uint8_t oem_name[8];
+  grub_uint16_t bytes_per_sector;
+  grub_uint8_t sectors_per_cluster;
+  grub_uint16_t num_reserved_sectors;
+  grub_uint8_t num_fats;
+  grub_uint16_t num_root_entries;
+  grub_uint16_t num_total_sectors_16;
+  grub_uint8_t media;
+  grub_uint16_t sectors_per_fat_16;
+  grub_uint16_t sectors_per_track;
+  grub_uint16_t num_heads;
+  grub_uint32_t num_hidden_sectors;
+  grub_uint32_t num_total_sectors_32;
+  union
+  {
+    struct
+    {
+      grub_uint8_t num_ph_drive;
+      grub_uint8_t reserved;
+      grub_uint8_t boot_sig;
+      grub_uint32_t num_serial;
+      grub_uint8_t label[11];
+      grub_uint8_t fstype[8];
+    } __attribute__ ((packed)) fat12_or_fat16;
+    struct
+    {
+      grub_uint32_t sectors_per_fat_32;
+      grub_uint16_t extended_flags;
+      grub_uint16_t fs_version;
+      grub_uint32_t root_cluster;
+      grub_uint16_t fs_info;
+      grub_uint16_t backup_boot_sector;
+      grub_uint8_t reserved[12];
+      grub_uint8_t num_ph_drive;
+      grub_uint8_t reserved1;
+      grub_uint8_t boot_sig;
+      grub_uint32_t num_serial;
+      grub_uint8_t label[11];
+      grub_uint8_t fstype[8];
+    } __attribute__ ((packed)) fat32;
+  } __attribute__ ((packed)) version_specific;
+} __attribute__ ((packed));
+
+struct grub_fat_dir_entry
+{
+  grub_uint8_t name[11];
+  grub_uint8_t attr;
+  grub_uint8_t nt_reserved;
+  grub_uint8_t c_time_tenth;
+  grub_uint16_t c_time;
+  grub_uint16_t c_date;
+  grub_uint16_t a_date;
+  grub_uint16_t first_cluster_high;
+  grub_uint16_t w_time;
+  grub_uint16_t w_date;
+  grub_uint16_t first_cluster_low;
+  grub_uint32_t file_size;
+} __attribute__ ((packed));
+
+struct grub_fat_long_name_entry
+{
+  grub_uint8_t id;
+  grub_uint16_t name1[5];
+  grub_uint8_t attr;
+  grub_uint8_t reserved;
+  grub_uint8_t checksum;
+  grub_uint16_t name2[6];
+  grub_uint16_t first_cluster;
+  grub_uint16_t name3[2];
+} __attribute__ ((packed));
+
+struct grub_fat_data
+{
+  int logical_sector_bits;
+  grub_uint32_t num_sectors;
+
+  grub_uint32_t fat_sector;
+  grub_uint32_t sectors_per_fat;
+  int fat_size;
+
+  grub_uint32_t root_cluster;
+  grub_uint32_t root_sector;
+  grub_uint32_t num_root_sectors;
+
+  int cluster_bits;
+  grub_uint32_t cluster_eof_mark;
+  grub_uint32_t cluster_sector;
+  grub_uint32_t num_clusters;
+
+  grub_uint8_t attr;
+  grub_ssize_t file_size;
+  grub_uint32_t file_cluster;
+  grub_uint32_t cur_cluster_num;
+  grub_uint32_t cur_cluster;
+
+  grub_uint32_t uuid;
+};
+
+
+
+
+
+
+
+struct grub_fat_data* 
+grub_fat_mount (BlockDriverState *bs, grub_uint32_t part_off_sector);
+
+grub_err_t
+grub_fat_open (grub_file_t file, const char *name);
+
+grub_err_t
+grub_fat_ls (grub_file_t file, const char *path,
+       int (*hook) (const char *filename,
+    const struct grub_dirhook_info *info,
+    void *closure),
+      void *closure);
+
+grub_err_t grub_fat_close(grub_file_t file);
+
+grub_ssize_t grub_fat_read(grub_file_t file, grub_off_t offset,
+   grub_size_t len, char *buf);
+
+
+#endif
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fs-comm.h xen-4.1.2-b/tools/ioemu-qemu-xen/fs-comm.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/fs-comm.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/fs-comm.h 2012-12-28 16:02:41.003846897 +0800
@@ -0,0 +1,60 @@
+#ifndef _FS_COMM_H
+#define _FS_COMM_H
+
+#include "fs-types.h"
+#include "block_int.h"
+#include "grub_err.h"
+#include "debug.h"
+
+typedef struct  grub_file
+{
+  void *data;
+  BlockDriverState *bs;
+  uint32_t part_off_sector;
+  grub_size_t size;
+  grub_off_t offset;
+  /* This is called when a sector is read. Used only for a disk device.  */
+  void (*read_hook) (grub_disk_addr_t sector,
+      unsigned offset, unsigned length, void *closure);
+  void *closure;
+}*grub_file_t;
+
+struct grub_dirhook_info
+{
+  unsigned dir:1;
+  unsigned mtimeset:1;
+  unsigned case_insensitive:1;
+  grub_uint32_t mtime;    //(date | time)
+  grub_uint32_t filesize;
+  grub_uint64_t filesize_ntfs;
+  grub_uint64_t time_ntfs;
+};
+
+struct ls_ctrl
+{
+  unsigned detail:1;
+  char* dirname;
+};
+
+
+
+
+typedef grub_err_t
+(*grub_open) (grub_file_t file, const char *name);
+
+typedef grub_err_t
+(*grub_ls) (grub_file_t file, const char *path,
+       int (*hook) (const char *filename,
+    const struct grub_dirhook_info *info,
+    void *closure),
+      void *closure);
+
+typedef grub_err_t 
+(*grub_close) (grub_file_t file);
+
+typedef grub_ssize_t 
+(*grub_read)(grub_file_t file, grub_off_t offset,
+   grub_size_t len, char *buf);
+
+
+#endif
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fshelp.c xen-4.1.2-b/tools/ioemu-qemu-xen/fshelp.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/fshelp.c 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/fshelp.c 2012-12-28 16:02:41.004932457 +0800
@@ -0,0 +1,362 @@
+/* fshelp.c -- Filesystem helper functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "err.h"
+#include "misc.h"
+#include "block_int.h"
+#include "fshelp.h"
+#include "ntfs.h"
+#include "debug.h"
+
+struct grub_fshelp_find_file_closure
+{
+  grub_fshelp_node_t rootnode;
+  int (*iterate_dir) (grub_fshelp_node_t dir,
+       int (*hook)
+       (const char *filename,
+        enum grub_fshelp_filetype filetype,
+        grub_fshelp_node_t node, void *closure),
+       void *closure);
+  void *closure;
+  char *(*read_symlink) (grub_fshelp_node_t node);
+  int symlinknest;
+  enum grub_fshelp_filetype foundtype;
+  grub_fshelp_node_t currroot;
+};
+
+static void
+free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_closure *c)
+{
+  if (node != c->rootnode && node != c->currroot)
+    grub_free (node);
+}
+
+struct find_file_closure
+{
+  char *name;
+  enum grub_fshelp_filetype *type;
+  grub_fshelp_node_t *oldnode;
+  grub_fshelp_node_t *currnode;
+};
+
+static int
+iterate (const char *filename,
+  enum grub_fshelp_filetype filetype,
+  grub_fshelp_node_t node,
+  void *closure)
+{
+  struct find_file_closure *c = closure;
+  DBG("list_file hooked by fshelp:iterate(), filename=%s", filename);
+  if (filetype == GRUB_FSHELP_UNKNOWN ||
+      (grub_strcmp (c->name, filename) &&
+       (! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
+ grub_strncasecmp (c->name, filename, GRUB_LONG_MAX))))
+    {
+      DBG("not match!!!>>>>>>");
+      grub_free (node);
+      return 0;
+    }
+
+  /* The node is found, stop iterating over the nodes.  */
+  *(c->type) = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
+  *(c->oldnode) = *(c->currnode);
+  *(c->currnode) = node;
+  DBG("found!!>>>>>>");
+  return 1;
+}
+
+static grub_err_t
+find_file (const char *currpath, grub_fshelp_node_t currroot,
+    grub_fshelp_node_t *currfound,
+    struct grub_fshelp_find_file_closure *c)
+{
+  char fpath[grub_strlen (currpath) + 1];
+  char *name = fpath;
+  char *next;
+  enum grub_fshelp_filetype type = GRUB_FSHELP_DIR;
+  grub_fshelp_node_t currnode = currroot;
+  grub_fshelp_node_t oldnode = currroot;
+
+  c->currroot = currroot;
+
+  grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1);
+
+  /* Remove all leading slashes.  */
+  while (*name == '/')
+    name++;
+
+  if (! *name)
+    {
+      *currfound = currnode;
+      return 0;
+    }
+
+  for (;;)
+    {
+      int found;
+      struct find_file_closure cc;
+
+      /* Extract the actual part from the pathname.  */
+      next = grub_strchr (name, '/');
+      if (next)
+ {
+   /* Remove all leading slashes.  */
+   while (*next == '/')
+     *(next++) = '\0';
+ }
+
+      /* At this point it is expected that the current node is a
+  directory, check if this is true.  */
+      if (type != GRUB_FSHELP_DIR)
+ {
+   free_node (currnode, c);
+   return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+ }
+
+      DBG("find_file_closure cc.name=【%s】", name);
+      cc.name = name;
+      cc.type = &type;
+      cc.oldnode = &oldnode;
+      cc.currnode = &currnode;
+      /* Iterate over the directory.  */
+      DBG("******fshelp:find_file hooked by \'grub_ntfs_iterate_dir\',"
+   "nested another hook \'fshelp:iterator\'");
+      found = c->iterate_dir (currnode, iterate, &cc); 
+      if (! found)
+ {
+   if (grub_errno)
+     return grub_errno;
+
+   break;
+ }
+
+      /* Read in the symlink and follow it.  */
+      if (type == GRUB_FSHELP_SYMLINK)
+ {
+   char *symlink;
+
+   /* Test if the symlink does not loop.  */
+   if (++(c->symlinknest) == 8)
+     {
+       free_node (currnode, c);
+       free_node (oldnode, c);
+       return grub_error (GRUB_ERR_SYMLINK_LOOP,
+  "too deep nesting of symlinks");
+     }
+
+   symlink = c->read_symlink (currnode);
+   free_node (currnode, c);
+
+   if (!symlink)
+     {
+       free_node (oldnode, c);
+       return grub_errno;
+     }
+
+   /* The symlink is an absolute path, go back to the root inode.  */
+   if (symlink[0] == '/')
+     {
+       free_node (oldnode, c);
+       oldnode = c->rootnode;
+     }
+
+   /* Lookup the node the symlink points to.  */
+   find_file (symlink, oldnode, &currnode, c);
+   type = c->foundtype;
+   grub_free (symlink);
+
+   if (grub_errno)
+     {
+       free_node (oldnode, c);
+       return grub_errno;
+     }
+ }
+
+      free_node (oldnode, c);
+
+      /* Found the node!  */
+      if (! next || *next == '\0')
+ {
+   *currfound = currnode;
+   c->foundtype = type;
+   return 0;
+ }
+
+      name = next;
+    }
+
+  return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+}
+
+/* Lookup the node PATH.  The node ROOTNODE describes the root of the
+   directory tree.  The node found is returned in FOUNDNODE, which is
+   either a ROOTNODE or a new malloc'ed node.  ITERATE_DIR is used to
+   iterate over all directory entries in the current node.
+   READ_SYMLINK is used to read the symlink if a node is a symlink.
+   EXPECTTYPE is the type node that is expected by the called, an
+   error is generated if the node is not of the expected type.  Make
+   sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
+   because GCC has a nasty bug when using regparm=3.  */
+grub_err_t
+grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
+        grub_fshelp_node_t *foundnode,
+        int (*iterate_dir) (grub_fshelp_node_t dir,
+    int (*hook)
+    (const char *filename,
+     enum grub_fshelp_filetype filetype,
+     grub_fshelp_node_t node,
+     void *closure),
+    void *closure),
+        void *closure,
+        char *(*read_symlink) (grub_fshelp_node_t node),
+        enum grub_fshelp_filetype expecttype)
+{
+  grub_err_t err;
+  struct grub_fshelp_find_file_closure c;
+
+  c.rootnode = rootnode;
+  c.iterate_dir = iterate_dir;
+  c.closure = closure;
+  c.read_symlink = read_symlink;
+  c.symlinknest = 0;
+  c.foundtype = GRUB_FSHELP_DIR;
+
+  if (!path || path[0] != '/')
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
+      return grub_errno;
+    }
+  
+  
+  DBG("going to find_file\n");
+  err = find_file (path, rootnode, foundnode, &c);
+  if (err)
+    return err;
+
+  /* Check if the node that was found was of the expected type.  */
+  if (expecttype == GRUB_FSHELP_REG && c.foundtype != expecttype)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file");
+  else if (expecttype == GRUB_FSHELP_DIR && c.foundtype != expecttype)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+
+  return 0;
+}
+
+/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
+   beginning with the block POS.  READ_HOOK should be set before
+   reading a block from the file.  GET_BLOCK is used to translate file
+   blocks to disk blocks.  The file is FILESIZE bytes big and the
+   blocks have a size of LOG2BLOCKSIZE (in log2).  */
+grub_ssize_t
+grub_fshelp_read_file (BlockDriverState* bs, grub_fshelp_node_t node,
+        void (*read_hook) (grub_disk_addr_t sector,
+   unsigned offset,
+   unsigned length,
+   void *closure),
+        void *closure,
+        grub_off_t pos, grub_size_t len, char *buf,
+        grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
+       grub_disk_addr_t block),
+        grub_off_t filesize, int log2blocksize)
+{
+  grub_disk_addr_t i, blockcnt;
+  grub_off_t off_bytes;
+  int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
+
+  /* Adjust LEN so it we can't read past the end of the file.  */
+  if (pos + len > filesize)
+    len = filesize - pos;
+
+  blockcnt = ((len + pos) + blocksize - 1) >>
+    (log2blocksize + GRUB_DISK_SECTOR_BITS);
+
+  for (i = pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS); i < blockcnt; i++)
+    {
+      grub_disk_addr_t blknr;
+      int blockoff = pos & (blocksize - 1);
+      int blockend = blocksize;
+
+      int skipfirst = 0;
+
+      blknr = get_block (node, i);
+      if (grub_errno)
+ return -1;
+
+      blknr = blknr << log2blocksize;
+      off_bytes = blknr << GRUB_DISK_SECTOR_BITS;
+
+      /* Last block.  */
+      if (i == blockcnt - 1)
+ {
+   blockend = (len + pos) & (blocksize - 1);
+
+   /* The last portion is exactly blocksize.  */
+   if (! blockend)
+     blockend = blocksize;
+ }
+
+      /* First block.  */
+      if (i == (pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS)))
+ {
+   skipfirst = blockoff;
+   blockend -= skipfirst;
+ }
+
+      /* If the block number is 0 this block is not stored on disk but
+  is zero filled instead.  */
+      if (blknr)
+ {
+   //bs->read_hook = read_hook;
+   //bs->closure = closure;
+   
+   bdrv_pread_from_lcn_of_volum(bs, off_bytes + skipfirst,
+       buf, blockend);
+   //bs->read_hook = 0;
+   if (grub_errno)
+     return -1;
+ }
+      else
+ grub_memset (buf, 0, blockend);
+
+      buf += blocksize - skipfirst;
+    }
+
+  return len;
+}
+
+unsigned int
+grub_fshelp_log2blksize (unsigned int blksize, unsigned int *pow)
+{
+  int mod;
+
+  *pow = 0;
+  while (blksize > 1)
+    {
+      mod = blksize - ((blksize >> 1) << 1);
+      blksize >>= 1;
+
+      /* Check if it really is a power of two.  */
+      if (mod)
+ return grub_error (GRUB_ERR_BAD_NUMBER,
+    "the blocksize is not a power of two");
+      (*pow)++;
+    }
+
+  return GRUB_ERR_NONE;
+}
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fshelp.h xen-4.1.2-b/tools/ioemu-qemu-xen/fshelp.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/fshelp.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/fshelp.h 2012-12-28 16:02:41.004932457 +0800
@@ -0,0 +1,86 @@
+/* fshelp.h -- Filesystem helper functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_FSHELP_HEADER
+#define GRUB_FSHELP_HEADER 1
+
+#include "fs-types.h"
+#include "grub_err.h"
+#include "block_int.h"
+typedef struct grub_fshelp_node *grub_fshelp_node_t;
+
+#define GRUB_FSHELP_CASE_INSENSITIVE 0x100
+#define GRUB_FSHELP_TYPE_MASK 0xff
+#define GRUB_FSHELP_FLAGS_MASK 0x100
+
+enum grub_fshelp_filetype
+  {
+    GRUB_FSHELP_UNKNOWN,
+    GRUB_FSHELP_REG,
+    GRUB_FSHELP_DIR,
+    GRUB_FSHELP_SYMLINK
+  };
+
+/* Lookup the node PATH.  The node ROOTNODE describes the root of the
+   directory tree.  The node found is returned in FOUNDNODE, which is
+   either a ROOTNODE or a new malloc'ed node.  ITERATE_DIR is used to
+   iterate over all directory entries in the current node.
+   READ_SYMLINK is used to read the symlink if a node is a symlink.
+   EXPECTTYPE is the type node that is expected by the called, an
+   error is generated if the node is not of the expected type.  Make
+   sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
+   because GCC has a nasty bug when using regparm=3.  */
+grub_err_t grub_fshelp_find_file (const char *path,
+   grub_fshelp_node_t rootnode,
+   grub_fshelp_node_t *foundnode,
+   int (*iterate_dir)
+   (grub_fshelp_node_t dir,
+    int (*hook)
+    (const char *filename,
+     enum grub_fshelp_filetype filetype,
+     grub_fshelp_node_t node,
+     void *closure),
+    void *closure),
+   void *closure,
+   char *(*read_symlink) (grub_fshelp_node_t node),
+   enum grub_fshelp_filetype expect);
+
+
+/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
+   beginning with the block POS.  READ_HOOK should be set before
+   reading a block from the file.  GET_BLOCK is used to translate file
+   blocks to disk blocks.  The file is FILESIZE bytes big and the
+   blocks have a size of LOG2BLOCKSIZE (in log2).  */
+grub_ssize_t grub_fshelp_read_file (BlockDriverState* bs, grub_fshelp_node_t node,
+     void (*read_hook)
+     (grub_disk_addr_t sector,
+      unsigned offset,
+      unsigned length,
+      void *closure),
+     void *closure,
+     grub_off_t pos, grub_size_t len, char *buf,
+     grub_disk_addr_t (*get_block)
+     (grub_fshelp_node_t node,
+      grub_disk_addr_t block),
+     grub_off_t filesize, int log2blocksize);
+
+unsigned int grub_fshelp_log2blksize (unsigned int blksize,
+       unsigned int *pow);
+
+#endif /* ! GRUB_FSHELP_HEADER */
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fs-time.c xen-4.1.2-b/tools/ioemu-qemu-xen/fs-time.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/fs-time.c 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/fs-time.c 2012-12-28 16:02:41.005685798 +0800
@@ -0,0 +1,77 @@
+#include "fs-time.h"
+
+
+
+static uint64_t div64(uint64_t a, uint32_t b, uint32_t c)
+{
+    union {
+        uint64_t ll;
+        struct {
+#ifdef WORDS_BIGENDIAN
+            uint32_t high, low;
+#else
+            uint32_t low, high;
+#endif
+        } l;
+    } u, res;
+    uint64_t rl, rh;
+
+    u.ll = a;
+    rl = (uint64_t)u.l.low * (uint64_t)b;
+    rh = (uint64_t)u.l.high * (uint64_t)b;
+    rh += (rl >> 32);
+    res.l.high = rh / c;
+    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+    return res.ll;
+}
+
+static uint64_t sub64(uint64_t a, uint64_t b)
+{
+  struct
+  {
+#ifdef WORDS_BIGENDIAN
+            uint32_t high, low;
+#else
+            uint32_t low, high;
+#endif
+  }a1,b1,c;
+  
+  a1.high = a>>32;
+  a1.low = a&0xffffffff;
+  b1.high = b>>32;
+  b1.low = b&0xffffffff;
+  
+  if(a1.high < b1.high)
+    {
+      c=b1;
+      b1=a1;
+      a1=c;
+    }
+  
+  a1.high -= b1.high;
+  a1.low -= b1.low;
+  if(a1.low & 0x80000000)
+    {
+      a1.low = (~(a1.low & 0x7fffffff))+1;
+      a1.high -= 1;
+    }
+  
+  uint64_t ret = (uint64_t)a1.high<<32 | a1.low;
+  return ret;
+}
+
+struct tm* ntfs_utc2local(grub_uint64_t time, struct tm* ptm)
+{
+  //time_t time2 = sub64(time, NTFS_TIME_OFFSET);
+  time_t time2 = time - NTFS_TIME_OFFSET;
+  /*DBG("sizeof(int)=%d", sizeof(int));
+  DBG("sizeof(short)=%d", sizeof(short));
+  DBG("sizeof(long)=%d", sizeof(long));
+  DBG("sizeof(long long)=%d", sizeof(unsigned long long));
+  DBG("sizeof(time_t)=%d, time=%zu, time2=%zu", sizeof(time_t), time, time2);*/
+  //time2 = div64(time2,1,10000000);
+  time2 = time2 / 10000000;
+  DBG("sizeof(time_t)=%d, time=%zu, time2=%zu", sizeof(time_t), time, time2);
+  ////time2 = 0;//time(NULL);
+  return localtime_r(&time2, ptm);
+}
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fs-time.h xen-4.1.2-b/tools/ioemu-qemu-xen/fs-time.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/fs-time.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/fs-time.h 2012-12-28 16:02:41.005685798 +0800
@@ -0,0 +1,12 @@
+#ifndef FS_TIME_H
+#define FS_TIME_H
+
+#include <time.h>
+#include "fs-comm.h"
+#define NTFS_TIME_OFFSET ((grub_uint64_t)(369 * 365 + 89) * 24 * 3600 * 10000000)
+
+struct tm* ntfs_utc2local(grub_uint64_t time, struct tm* ptm);
+
+
+#endif
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fs-types.h xen-4.1.2-b/tools/ioemu-qemu-xen/fs-types.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/fs-types.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/fs-types.h 2012-12-28 16:02:41.006932417 +0800
@@ -0,0 +1,234 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_HEADER
+#define GRUB_TYPES_HEADER 1
+
+#include "grub-config.h"
+#include "x86_64/types.h"
+
+#ifdef GRUB_UTIL
+# define GRUB_CPU_SIZEOF_VOID_P SIZEOF_VOID_P
+# define GRUB_CPU_SIZEOF_LONG SIZEOF_LONG
+# ifdef WORDS_BIGENDIAN
+#  define GRUB_CPU_WORDS_BIGENDIAN 1
+# else
+#  undef GRUB_CPU_WORDS_BIGENDIAN
+# endif
+#else /* ! GRUB_UTIL */
+# define GRUB_CPU_SIZEOF_VOID_P GRUB_TARGET_SIZEOF_VOID_P
+# define GRUB_CPU_SIZEOF_LONG GRUB_TARGET_SIZEOF_LONG
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define GRUB_CPU_WORDS_BIGENDIAN 1
+# else
+#  undef GRUB_CPU_WORDS_BIGENDIAN
+# endif
+#endif /* ! GRUB_UTIL */
+
+#if GRUB_CPU_SIZEOF_VOID_P != 4 && GRUB_CPU_SIZEOF_VOID_P != 8
+# error "This architecture is not supported because sizeof(void *) != 4 and sizeof(void *) != 8"
+#endif
+
+#ifndef GRUB_TARGET_WORDSIZE
+# if GRUB_TARGET_SIZEOF_VOID_P == 4
+#  define GRUB_TARGET_WORDSIZE 32
+# elif GRUB_TARGET_SIZEOF_VOID_P == 8
+#  define GRUB_TARGET_WORDSIZE 64
+# endif
+#endif
+
+/* Define various wide integers.  */
+typedef signed char grub_int8_t;
+typedef short grub_int16_t;
+typedef int grub_int32_t;
+#if GRUB_CPU_SIZEOF_LONG == 8
+typedef long grub_int64_t;
+#else
+typedef long long grub_int64_t;
+#endif
+
+typedef unsigned char grub_uint8_t;
+typedef unsigned short grub_uint16_t;
+typedef unsigned grub_uint32_t;
+#if GRUB_CPU_SIZEOF_LONG == 8
+typedef unsigned long grub_uint64_t;
+#else
+typedef unsigned long long grub_uint64_t;
+#endif
+
+/* Misc types.  */
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+typedef grub_uint64_t grub_target_addr_t;
+typedef grub_uint64_t grub_target_off_t;
+typedef grub_uint64_t grub_target_size_t;
+typedef grub_int64_t grub_target_ssize_t;
+#else
+typedef grub_uint32_t grub_target_addr_t;
+typedef grub_uint32_t grub_target_off_t;
+typedef grub_uint32_t grub_target_size_t;
+typedef grub_int32_t grub_target_ssize_t;
+#endif
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+typedef grub_uint64_t grub_addr_t;
+typedef grub_uint64_t grub_size_t;
+typedef grub_int64_t grub_ssize_t;
+#else
+typedef grub_uint32_t grub_addr_t;
+typedef grub_uint32_t grub_size_t;
+typedef grub_int32_t grub_ssize_t;
+#endif
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+# define GRUB_ULONG_MAX 18446744073709551615UL
+# define GRUB_LONG_MAX 9223372036854775807L
+# define GRUB_LONG_MIN (-9223372036854775807L - 1)
+#else
+# define GRUB_ULONG_MAX 4294967295UL
+# define GRUB_LONG_MAX 2147483647L
+# define GRUB_LONG_MIN (-2147483647L - 1)
+#endif
+
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+#define UINT_TO_PTR(x) ((void*)(grub_uint32_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(grub_uint32_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(x))
+#else
+#define UINT_TO_PTR(x) ((void*)(grub_uint64_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(grub_uint64_t)(x))
+#endif
+
+/* The type for representing a file offset.  */
+typedef grub_uint64_t grub_off_t;
+
+/* The type for representing a disk block address.  */
+typedef grub_uint64_t grub_disk_addr_t;
+
+/* Byte-orders.  */
+#define grub_swap_bytes16(x) \
+({ \
+   grub_uint16_t _x = (x); \
+   (grub_uint16_t) ((_x << 8) | (_x >> 8)); \
+})
+
+#if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) && defined(GRUB_TARGET_I386)
+static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x)
+{
+ return __builtin_bswap32(x);
+}
+
+static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
+{
+ return __builtin_bswap64(x);
+}
+#else /* not gcc 4.3 or newer */
+#define grub_swap_bytes32(x) \
+({ \
+   grub_uint32_t _x = (x); \
+   (grub_uint32_t) ((_x << 24) \
+                    | ((_x & (grub_uint32_t) 0xFF00UL) << 8) \
+                    | ((_x & (grub_uint32_t) 0xFF0000UL) >> 8) \
+                    | (_x >> 24)); \
+})
+
+#define grub_swap_bytes64(x) \
+({ \
+   grub_uint64_t _x = (x); \
+   (grub_uint64_t) ((_x << 56) \
+                    | ((_x & (grub_uint64_t) 0xFF00ULL) << 40) \
+                    | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) \
+                    | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) \
+                    | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) \
+                    | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) \
+                    | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) \
+                    | (_x >> 56)); \
+})
+#endif /* not gcc 4.3 or newer */
+
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+# define grub_cpu_to_le16(x) grub_swap_bytes16(x)
+# define grub_cpu_to_le32(x) grub_swap_bytes32(x)
+# define grub_cpu_to_le64(x) grub_swap_bytes64(x)
+# define grub_le_to_cpu16(x) grub_swap_bytes16(x)
+# define grub_le_to_cpu32(x) grub_swap_bytes32(x)
+# define grub_le_to_cpu64(x) grub_swap_bytes64(x)
+# define grub_cpu_to_be16(x) ((grub_uint16_t) (x))
+# define grub_cpu_to_be32(x) ((grub_uint32_t) (x))
+# define grub_cpu_to_be64(x) ((grub_uint64_t) (x))
+# define grub_be_to_cpu16(x) ((grub_uint16_t) (x))
+# define grub_be_to_cpu32(x) ((grub_uint32_t) (x))
+# define grub_be_to_cpu64(x) ((grub_uint64_t) (x))
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define grub_target_to_host16(x) ((grub_uint16_t) (x))
+#  define grub_target_to_host32(x) ((grub_uint32_t) (x))
+#  define grub_target_to_host64(x) ((grub_uint64_t) (x))
+#  define grub_host_to_target16(x) ((grub_uint16_t) (x))
+#  define grub_host_to_target32(x) ((grub_uint32_t) (x))
+#  define grub_host_to_target64(x) ((grub_uint64_t) (x))
+# else /* ! GRUB_TARGET_WORDS_BIGENDIAN */
+#  define grub_target_to_host16(x) grub_swap_bytes16(x)
+#  define grub_target_to_host32(x) grub_swap_bytes32(x)
+#  define grub_target_to_host64(x) grub_swap_bytes64(x)
+#  define grub_host_to_target16(x) grub_swap_bytes16(x)
+#  define grub_host_to_target32(x) grub_swap_bytes32(x)
+#  define grub_host_to_target64(x) grub_swap_bytes64(x)
+# endif
+#else /* ! WORDS_BIGENDIAN */
+# define grub_cpu_to_le16(x) ((grub_uint16_t) (x))
+# define grub_cpu_to_le32(x) ((grub_uint32_t) (x))
+# define grub_cpu_to_le64(x) ((grub_uint64_t) (x))
+# define grub_le_to_cpu16(x) ((grub_uint16_t) (x))
+# define grub_le_to_cpu32(x) ((grub_uint32_t) (x))
+# define grub_le_to_cpu64(x) ((grub_uint64_t) (x))
+# define grub_cpu_to_be16(x) grub_swap_bytes16(x)
+# define grub_cpu_to_be32(x) grub_swap_bytes32(x)
+# define grub_cpu_to_be64(x) grub_swap_bytes64(x)
+# define grub_be_to_cpu16(x) grub_swap_bytes16(x)
+# define grub_be_to_cpu32(x) grub_swap_bytes32(x)
+# define grub_be_to_cpu64(x) grub_swap_bytes64(x)
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define grub_target_to_host16(x) grub_swap_bytes16(x)
+#  define grub_target_to_host32(x) grub_swap_bytes32(x)
+#  define grub_target_to_host64(x) grub_swap_bytes64(x)
+#  define grub_host_to_target16(x) grub_swap_bytes16(x)
+#  define grub_host_to_target32(x) grub_swap_bytes32(x)
+#  define grub_host_to_target64(x) grub_swap_bytes64(x)
+# else /* ! GRUB_TARGET_WORDS_BIGENDIAN */
+#  define grub_target_to_host16(x) ((grub_uint16_t) (x))
+#  define grub_target_to_host32(x) ((grub_uint32_t) (x))
+#  define grub_target_to_host64(x) ((grub_uint64_t) (x))
+#  define grub_host_to_target16(x) ((grub_uint16_t) (x))
+#  define grub_host_to_target32(x) ((grub_uint32_t) (x))
+#  define grub_host_to_target64(x) ((grub_uint64_t) (x))
+# endif
+#endif /* ! WORDS_BIGENDIAN */
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+#  define grub_host_to_target_addr(x) grub_host_to_target64(x)
+#else
+#  define grub_host_to_target_addr(x) grub_host_to_target32(x)
+#endif
+
+
+
+
+
+
+
+#endif /* ! GRUB_TYPES_HEADER */
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-config.h xen-4.1.2-b/tools/ioemu-qemu-xen/grub-config.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-config.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-config.h 2012-12-28 16:02:41.006932417 +0800
@@ -0,0 +1,251 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define it if GAS requires that absolute indirect calls/jumps are not
+   prefixed with an asterisk */
+/* #undef ABSOLUTE_WITHOUT_ASTERISK */
+
+/* Define it to \"addr32\" or \"addr32;\" to make GAS happy */
+#define ADDR32 addr32
+
+/* Define it to \"data32\" or \"data32;\" to make GAS happy */
+#define DATA32 data32
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#define ENABLE_NLS 1
+
+/* Define if C symbols get an underscore after compilation */
+/* #undef HAVE_ASM_USCORE */
+
+/* Define to 1 if you have the `asprintf' function. */
+#define HAVE_ASPRINTF 1
+
+/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
+   CoreFoundation framework. */
+/* #undef HAVE_CFLOCALECOPYCURRENT */
+
+/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
+   the CoreFoundation framework. */
+/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
+
+/* Define to 1 if you have the <curses.h> header file. */
+/* #undef HAVE_CURSES_H */
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+#define HAVE_DCGETTEXT 1
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <ft2build.h> header file. */
+#define HAVE_FT2BUILD_H 1
+
+/* Define to 1 if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define if getrawpartition() in -lutil can be used */
+/* #undef HAVE_GETRAWPARTITION */
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#define HAVE_GETTEXT 1
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the iconv() function and it works. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the `memalign' function. */
+#define HAVE_MEMALIGN 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <ncurses/curses.h> header file. */
+/* #undef HAVE_NCURSES_CURSES_H */
+
+/* Define to 1 if you have the <ncurses.h> header file. */
+/* #undef HAVE_NCURSES_H */
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if opendisk() in -lutil can be used */
+/* #undef HAVE_OPENDISK */
+
+/* Define to 1 if you have the <pci/pci.h> header file. */
+/* #undef HAVE_PCI_PCI_H */
+
+/* Define to 1 if you have the `posix_memalign' function. */
+#define HAVE_POSIX_MEMALIGN 1
+
+/* Define if returns_twice attribute is supported */
+/* #undef HAVE_RETURNS_TWICE */
+
+/* Define to 1 if you have the `sbrk' function. */
+#define HAVE_SBRK 1
+
+/* Define to 1 if you have the <SDL/SDL.h> header file. */
+/* #undef HAVE_SDL_SDL_H */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/fcntl.h> header file. */
+#define HAVE_SYS_FCNTL_H 1
+
+/* Define to 1 if you have the <sys/mkdev.h> header file. */
+/* #undef HAVE_SYS_MKDEV_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#define HAVE_SYS_SYSMACROS_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <usb.h> header file. */
+/* #undef HAVE_USB_H */
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+   */
+/* #undef MAJOR_IN_MKDEV */
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in
+   <sysmacros.h>. */
+/* #undef MAJOR_IN_SYSMACROS */
+
+/* Define to 1 if you enable memory manager debugging. */
+/* #undef MM_DEBUG */
+
+/* Define to 1 if GCC generates calls to __register_frame_info() */
+/* #undef NEED_REGISTER_FRAME_INFO */
+
+/* Name of package */
+#define PACKAGE "burg"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "address@hidden"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "BURG"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "BURG 1.98"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "burg"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.98"
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* The size of `void *', as computed by sizeof. */
+#define SIZEOF_VOID_P 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "1.98"
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel and VAX). */
+#if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+#elif ! defined __LITTLE_ENDIAN__
+/* # undef WORDS_BIGENDIAN */
+#endif
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#define YYTEXT_POINTER 1
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub_err.c xen-4.1.2-b/tools/ioemu-qemu-xen/grub_err.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub_err.c 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub_err.c 2012-12-28 16:02:41.007734164 +0800
@@ -0,0 +1,186 @@
+/* err.c - error handling routines */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2007,2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "grub_err.h"
+#include "misc.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GRUB_MAX_ERRMSG 256
+#define GRUB_ERROR_STACK_SIZE 10
+
+grub_err_t grub_errno;
+char grub_errmsg[GRUB_MAX_ERRMSG];
+
+static struct
+{
+  grub_err_t errno;
+  char errmsg[GRUB_MAX_ERRMSG];
+} grub_error_stack_items[GRUB_ERROR_STACK_SIZE];
+
+static int grub_error_stack_pos;
+static int grub_error_stack_assert;
+
+
+
+static int
+grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap)
+{
+  grub_size_t ret;
+
+  if (!n)
+    return 0;
+
+  
+  ret = vsnprintf(str, n, fmt, ap);
+  printf("%s\n", str);
+  return ret < n ? ret : n;
+}
+
+
+
+static int
+grub_vprintf (const char *fmt, va_list args)
+{
+  int ret;
+
+  ret = grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), fmt, args);
+
+  return ret;
+}
+
+int
+grub_err_printf (const char *fmt, ...)
+{
+  va_list ap;
+  int ret;
+
+  va_start (ap, fmt);
+  ret = grub_vprintf (fmt, ap);
+  va_end (ap);
+
+  return ret;
+}
+
+
+grub_err_t
+grub_error (grub_err_t n, const char *fmt, ...)
+{
+  va_list ap;
+
+  grub_errno = n;
+  va_start (ap, fmt);
+  grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), fmt, ap);
+  va_end (ap);
+  
+  return n;
+}
+
+void
+grub_fatal (const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  grub_vprintf (_(fmt), ap);
+  va_end (ap);
+
+  exit(1);
+}
+
+void
+grub_error_push (void)
+{
+  /* Only add items to stack, if there is enough room.  */
+  if (grub_error_stack_pos < GRUB_ERROR_STACK_SIZE)
+    {
+      /* Copy active error message to stack.  */
+      grub_error_stack_items[grub_error_stack_pos].errno = grub_errno;
+      grub_memcpy (grub_error_stack_items[grub_error_stack_pos].errmsg,
+                   grub_errmsg,
+                   sizeof (grub_errmsg));
+
+      /* Advance to next error stack position.  */
+      grub_error_stack_pos++;
+    }
+  else
+    {
+      /* There is no room for new error message. Discard new error message
+         and mark error stack assertion flag.  */
+      grub_error_stack_assert = 1;
+    }
+
+  /* Allow further operation of other components by resetting
+     active errno to GRUB_ERR_NONE.  */
+  grub_errno = GRUB_ERR_NONE;
+}
+
+int
+grub_error_pop (void)
+{
+  if (grub_error_stack_pos > 0)
+    {
+      /* Pop error message from error stack to current active error.  */
+      grub_error_stack_pos--;
+
+      grub_errno = grub_error_stack_items[grub_error_stack_pos].errno;
+      grub_memcpy (grub_errmsg,
+                   grub_error_stack_items[grub_error_stack_pos].errmsg,
+                   sizeof (grub_errmsg));
+
+      return 1;
+    }
+  else
+    {
+      /* There is no more items on error stack, reset to no error state.  */
+      grub_errno = GRUB_ERR_NONE;
+
+      return 0;
+    }
+}
+
+void
+grub_print_error (void)
+{
+  /* Print error messages in reverse order. First print active error message
+     and then empty error stack.  */
+  do
+    {
+      if (grub_errno != GRUB_ERR_NONE)
+        grub_err_printf ("error: %s.\n", grub_errmsg);
+    }
+  while (grub_error_pop ());
+
+  /* If there was an assert while using error stack, report about it.  */
+  if (grub_error_stack_assert)
+    {
+      grub_err_printf ("assert: error stack overflow detected!\n");
+      grub_error_stack_assert = 0;
+    }
+}
+
+
+int test_grub_err()
+{
+  grub_error(222, "test %s\n", "grub_error");
+  grub_err_printf("test %s\n", "grub_err_printf");
+  grub_fatal("test %s\n", "grub_fatal");
+}
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub_err.h xen-4.1.2-b/tools/ioemu-qemu-xen/grub_err.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub_err.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub_err.h 2012-12-28 16:02:41.007734164 +0800
@@ -0,0 +1,81 @@
+/* err.h - error numbers and prototypes */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2007,2008 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_ERR_HEADER
+#define GRUB_ERR_HEADER 1
+
+
+typedef enum
+  {
+    GRUB_ERR_NONE = 0,
+    GRUB_ERR_TEST_FAILURE,
+    GRUB_ERR_BAD_MODULE,
+    GRUB_ERR_OUT_OF_MEMORY,
+    GRUB_ERR_BAD_FILE_TYPE,
+    GRUB_ERR_FILE_NOT_FOUND,
+    GRUB_ERR_FILE_READ_ERROR,
+    GRUB_ERR_BAD_FILENAME,
+    GRUB_ERR_UNKNOWN_FS,
+    GRUB_ERR_BAD_FS,
+    GRUB_ERR_BAD_NUMBER,
+    GRUB_ERR_OUT_OF_RANGE,
+    GRUB_ERR_UNKNOWN_DEVICE,
+    GRUB_ERR_BAD_DEVICE,
+    GRUB_ERR_READ_ERROR,
+    GRUB_ERR_WRITE_ERROR,
+    GRUB_ERR_UNKNOWN_COMMAND,
+    GRUB_ERR_INVALID_COMMAND,
+    GRUB_ERR_BAD_ARGUMENT,
+    GRUB_ERR_BAD_PART_TABLE,
+    GRUB_ERR_UNKNOWN_OS,
+    GRUB_ERR_BAD_OS,
+    GRUB_ERR_NO_KERNEL,
+    GRUB_ERR_BAD_FONT,
+    GRUB_ERR_NOT_IMPLEMENTED_YET,
+    GRUB_ERR_SYMLINK_LOOP,
+    GRUB_ERR_BAD_GZIP_DATA,
+    GRUB_ERR_MENU,
+    GRUB_ERR_TIMEOUT,
+    GRUB_ERR_IO,
+    GRUB_ERR_ACCESS_DENIED,
+    GRUB_ERR_MENU_ESCAPE,
+    GRUB_ERR_NOT_FOUND,
+    GRUB_ERR_UNKNOWN
+
+  }
+grub_err_t;
+
+
+#ifndef _
+# define _(String) String
+#endif
+
+extern grub_err_t grub_errno;
+extern char grub_errmsg[];
+
+grub_err_t grub_error (grub_err_t n, const char *fmt, ...);
+void grub_fatal (const char *fmt, ...) __attribute__((noreturn));
+void grub_error_push (void);
+int grub_error_pop (void);
+void grub_print_error (void);
+int grub_err_printf (const char *fmt, ...)
+     __attribute__ ((format (printf, 1, 2)));
+int test_grub_err(void);
+
+#endif /* ! GRUB_ERR_HEADER */
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/config.h xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/config.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/config.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/config.h 2012-12-28 16:02:41.008640838 +0800
@@ -0,0 +1,251 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define it if GAS requires that absolute indirect calls/jumps are not
+   prefixed with an asterisk */
+/* #undef ABSOLUTE_WITHOUT_ASTERISK */
+
+/* Define it to \"addr32\" or \"addr32;\" to make GAS happy */
+#define ADDR32 addr32
+
+/* Define it to \"data32\" or \"data32;\" to make GAS happy */
+#define DATA32 data32
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#define ENABLE_NLS 1
+
+/* Define if C symbols get an underscore after compilation */
+/* #undef HAVE_ASM_USCORE */
+
+/* Define to 1 if you have the `asprintf' function. */
+#define HAVE_ASPRINTF 1
+
+/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
+   CoreFoundation framework. */
+/* #undef HAVE_CFLOCALECOPYCURRENT */
+
+/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
+   the CoreFoundation framework. */
+/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
+
+/* Define to 1 if you have the <curses.h> header file. */
+/* #undef HAVE_CURSES_H */
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+#define HAVE_DCGETTEXT 1
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <ft2build.h> header file. */
+#define HAVE_FT2BUILD_H 1
+
+/* Define to 1 if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define if getrawpartition() in -lutil can be used */
+/* #undef HAVE_GETRAWPARTITION */
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#define HAVE_GETTEXT 1
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the iconv() function and it works. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the `memalign' function. */
+#define HAVE_MEMALIGN 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <ncurses/curses.h> header file. */
+/* #undef HAVE_NCURSES_CURSES_H */
+
+/* Define to 1 if you have the <ncurses.h> header file. */
+/* #undef HAVE_NCURSES_H */
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if opendisk() in -lutil can be used */
+/* #undef HAVE_OPENDISK */
+
+/* Define to 1 if you have the <pci/pci.h> header file. */
+/* #undef HAVE_PCI_PCI_H */
+
+/* Define to 1 if you have the `posix_memalign' function. */
+#define HAVE_POSIX_MEMALIGN 1
+
+/* Define if returns_twice attribute is supported */
+/* #undef HAVE_RETURNS_TWICE */
+
+/* Define to 1 if you have the `sbrk' function. */
+#define HAVE_SBRK 1
+
+/* Define to 1 if you have the <SDL/SDL.h> header file. */
+/* #undef HAVE_SDL_SDL_H */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/fcntl.h> header file. */
+#define HAVE_SYS_FCNTL_H 1
+
+/* Define to 1 if you have the <sys/mkdev.h> header file. */
+/* #undef HAVE_SYS_MKDEV_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#define HAVE_SYS_SYSMACROS_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <usb.h> header file. */
+/* #undef HAVE_USB_H */
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+   */
+/* #undef MAJOR_IN_MKDEV */
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in
+   <sysmacros.h>. */
+/* #undef MAJOR_IN_SYSMACROS */
+
+/* Define to 1 if you enable memory manager debugging. */
+/* #undef MM_DEBUG */
+
+/* Define to 1 if GCC generates calls to __register_frame_info() */
+/* #undef NEED_REGISTER_FRAME_INFO */
+
+/* Name of package */
+#define PACKAGE "burg"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "address@hidden"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "BURG"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "BURG 1.98"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "burg"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.98"
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* The size of `void *', as computed by sizeof. */
+#define SIZEOF_VOID_P 8
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "1.98"
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel and VAX). */
+#if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+#elif ! defined __LITTLE_ENDIAN__
+/* # undef WORDS_BIGENDIAN */
+#endif
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#define YYTEXT_POINTER 1
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/fat.c xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/fat.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/fat.c 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/fat.c 2012-12-28 16:02:41.008640838 +0800
@@ -0,0 +1,711 @@
+/* fat.c - FAT filesystem */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "misc.h"
+#include "fat.h"
+
+
+static int
+fat_log2 (unsigned x)
+{
+  int i;
+
+  if (x == 0)
+    return -1;
+
+  for (i = 0; (x & 1) == 0; i++)
+    x >>= 1;
+
+  if (x != 1)
+    return -1;
+
+  return i;
+}
+
+
+struct grub_fat_data *
+grub_fat_mount (BlockDriverState *bs, uint32_t part_off_sector)
+{
+  struct grub_fat_bpb bpb;
+  struct grub_fat_data *data = "">
+  grub_uint32_t first_fat, magic;
+  int64_t off_bytes = (int64_t)part_off_sector << GRUB_DISK_SECTOR_BITS;
+
+  if (! bs)
+    goto fail;
+
+  data = "" grub_fat_data *) malloc (sizeof (*data));
+  if (! data)
+    goto fail;
+
+  /* Read the BPB.  */
+  if (bdrv_pread(bs, off_bytes, &bpb, sizeof(bpb)) != sizeof(bpb))
+    {
+      printf("bdrv_pread fail....\n");
+      goto fail;
+    }
+    
+  if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT12", 5)
+      && grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT16", 5)
+      && grub_strncmp((const char *) bpb.version_specific.fat32.fstype, "FAT32", 5))
+    {
+      
+      printf("fail here-->grub_strncmp......line[%u]\n", __LINE__);
+      goto fail;
+    }
+
+  /* Get the sizes of logical sectors and clusters.  */
+  data->logical_sector_bits =
+    fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector));
+  printf("bpb.bytes_per_sector=0x%x, le_to_cpu16=0x%x\n",
+  bpb.bytes_per_sector, grub_le_to_cpu16 (bpb.bytes_per_sector));
+  
+
+  if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS)
+  {
+    printf("fail here-->logical_sector_bits......line[%u]\n", __LINE__); 
+    goto fail;
+  }
+  data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
+
+  printf("bpb.sectors_per_cluster=%u\n", bpb.sectors_per_cluster);
+  data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
+  if (data->cluster_bits < 0)
+    {
+      printf("fail here-->cluster_bits......line[%u]\n", __LINE__); 
+      goto fail;
+    }
+  data->cluster_bits += data->logical_sector_bits;
+
+  /* Get information about FATs.  */
+  printf("bpb.num_reserved_sectors=%u, le_to_cpu16=%u\n",
+  bpb.num_reserved_sectors, grub_le_to_cpu16 (bpb.num_reserved_sectors));
+  data->fat_sector = part_off_sector + (grub_le_to_cpu16 (bpb.num_reserved_sectors)
+       << data->logical_sector_bits);
+  printf("data->fat_sector=%u\n", data->fat_sector);
+  if (data->fat_sector == 0)
+    {
+      printf("fail here-->fat_sector......line[%u]\n", __LINE__); 
+      goto fail;
+    }
+  data->sectors_per_fat = ((bpb.sectors_per_fat_16
+     ? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
+     : grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32))
+    << data->logical_sector_bits);
+  printf("bpb.version_specific.fat32.sectors_per_fat_32=%u\n"
+  "grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32)=%u\n",
+  bpb.version_specific.fat32.sectors_per_fat_32,
+  grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32));
+  if (data->sectors_per_fat == 0)
+    goto fail;
+
+  /* Get the number of sectors in this volume.  */
+  data->num_sectors = ((bpb.num_total_sectors_16
+ ? grub_le_to_cpu16 (bpb.num_total_sectors_16)
+ : grub_le_to_cpu32 (bpb.num_total_sectors_32))
+        << data->logical_sector_bits);
+  if (data->num_sectors == 0)
+    {
+      printf("fail here-->num_sectors......line[%u]\n", __LINE__); 
+      goto fail;
+    }
+  /* Get information about the root directory.  */
+  if (bpb.num_fats == 0)
+    {
+      printf("fail here-->num_fats......line[%u]\n", __LINE__); 
+      goto fail;
+    }
+  data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
+  data->num_root_sectors
+    = ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries)
+  * GRUB_FAT_DIR_ENTRY_SIZE
+  + grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
+ >> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
+       << (data->logical_sector_bits));
+
+  data->cluster_sector = data->root_sector + data->num_root_sectors;
+  data->num_clusters = (((data->num_sectors - data->cluster_sector)
+  >> (data->cluster_bits + data->logical_sector_bits))
+ + 2);
+
+  if (data->num_clusters <= 2)
+    {
+      printf("fail here-->num_clusters......line[%u]\n", __LINE__); 
+      goto fail;
+    }
+  if (! bpb.sectors_per_fat_16)
+    {
+      /* FAT32.  */
+      grub_uint16_t flags = grub_le_to_cpu16 (bpb.version_specific.fat32.extended_flags);
+
+      data->root_cluster = grub_le_to_cpu32 (bpb.version_specific.fat32.root_cluster);
+      data->fat_size = 32;
+      data->cluster_eof_mark = 0x0ffffff8;
+
+      if (flags & 0x80)
+ {
+   /* Get an active FAT.  */
+   unsigned active_fat = flags & 0xf;
+
+   if (active_fat > bpb.num_fats)
+     goto fail;
+
+   data->fat_sector += active_fat * data->sectors_per_fat;
+ }
+
+      if (bpb.num_root_entries != 0 || bpb.version_specific.fat32.fs_version != 0)
+ goto fail;
+    }
+  else
+    {
+      /* FAT12 or FAT16.  */
+      data->root_cluster = ~0U;
+
+      if (data->num_clusters <= 4085 + 2)
+ {
+   /* FAT12.  */
+   data->fat_size = 12;
+   data->cluster_eof_mark = 0x0ff8;
+ }
+      else
+ {
+   /* FAT16.  */
+   data->fat_size = 16;
+   data->cluster_eof_mark = 0xfff8;
+ }
+    }
+
+  /* More sanity checks.  */
+  if (data->num_sectors <= data->fat_sector)
+    goto fail;
+
+  
+  printf("data->fat_sector=%u, data->sectors_per_fat=%u\n",
+  data->fat_sector, data->sectors_per_fat);
+  if (bdrv_pread(bs,
+  data->fat_sector << GRUB_DISK_SECTOR_BITS,
+  &first_fat,
+  sizeof (first_fat)) != sizeof(first_fat))
+    {
+      printf("fail here-->bdrv_pread......line[%u]\n", __LINE__); 
+      goto fail;
+    }
+
+  first_fat = grub_le_to_cpu32 (first_fat);
+
+  if (data->fat_size == 32)
+    {
+      first_fat &= 0x0fffffff;
+      magic = 0x0fffff00;
+    }
+  else if (data->fat_size == 16)
+    {
+      first_fat &= 0x0000ffff;
+      magic = 0xff00;
+    }
+  else
+    {
+      first_fat &= 0x00000fff;
+      magic = 0x0f00;
+    }
+
+  /* Serial number.  */
+  if (bpb.sectors_per_fat_16)
+    data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
+  else
+    data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
+
+  /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
+     descriptor, even if it is a so-called superfloppy (e.g. an USB key).
+     The check may be too strict for this kind of stupid BIOSes, as
+     they overwrite the media descriptor.  */
+  if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
+    {
+      printf("fail here-->first_fat=0x%x, magic=0x%x......line[%u]\n",
+      first_fat, magic, __LINE__); 
+      goto fail;
+    }
+  /* Start from the root directory.  */
+  data->file_cluster = data->root_cluster;
+  data->cur_cluster_num = ~0U;
+  data->attr = GRUB_FAT_ATTR_DIRECTORY;
+  printf("data->file_cluster=%u \ndata->cur_cluster_num=%u \ndata->attr=0x%x\n"
+  "data->logical_sector_bits=%u\n"
+  "data->cluster_bits=%u\n",
+  data->file_cluster, data->cur_cluster_num, data->attr,
+  data->logical_sector_bits, data->cluster_bits);
+  return data;
+
+ fail:
+
+  free (data);
+  errx ("not a FAT filesystem...\n");
+  return 0;
+}
+
+
+
+//从文件的指定偏移offset字节处读取len字节的数据到buf
+//文件由data->file_cluster指定
+//data->file_cluster指定了文件的起始簇号
+//默认data->file_cluster=2,代表根目录
+static grub_ssize_t
+grub_fat_read_data (BlockDriverState *bs, struct grub_fat_data *data,
+     void (*read_hook) (grub_disk_addr_t sector,
+        unsigned offset, unsigned length,
+        void *closure),
+     void *closure,
+     grub_off_t offset, grub_size_t len, char *buf)
+{
+  grub_size_t size;
+  grub_uint32_t logical_cluster;
+  unsigned logical_cluster_bits;
+  grub_ssize_t ret = 0;
+  unsigned long sector;
+  uint64_t off_bytes = 0; 
+  /* This is a special case. FAT12 and FAT16 doesn't have the root directory
+     in clusters.  */
+  if (data->file_cluster == ~0U)
+    {
+      size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
+      if (size > len)
+ size = len;
+
+      off_bytes = ((uint64_t)data->root_sector << GRUB_DISK_SECTOR_BITS) + offset;
+      if(bdrv_read(bs, off_bytes, buf, size ) != size) 
+ return -1;
+
+      return size;
+    }
+
+  /* Calculate the logical cluster number and offset.  */
+  logical_cluster_bits = (data->cluster_bits
+   + data->logical_sector_bits
+   + GRUB_DISK_SECTOR_BITS);
+  logical_cluster = offset >> logical_cluster_bits;    //which cluster to read 
+  offset &= (1 << logical_cluster_bits) - 1;           //mod
+
+  if (logical_cluster < data->cur_cluster_num)   //
+    {
+      data->cur_cluster_num = 0;
+      data->cur_cluster = data->file_cluster; // 第2个fat表项开始记录目录和文件
+    }
+
+  while (len)
+    {
+      while (logical_cluster > data->cur_cluster_num)
+ {
+   /* Find next cluster.  */
+   grub_uint32_t next_cluster;
+   unsigned long fat_offset;
+
+   switch (data->fat_size)
+     {
+     case 32:
+       fat_offset = data->cur_cluster << 2;
+       break;
+     case 16:
+       fat_offset = data->cur_cluster << 1;
+       break;
+     default:
+       /* case 12: */
+       fat_offset = data->cur_cluster + (data->cur_cluster >> 1);
+       break;
+     }
+
+   /* Read the FAT.  */
+   int len = (data->fat_size + 7) >> 3;
+   uint64_t off_bytes =  ((uint64_t)data->fat_sector << GRUB_DISK_SECTOR_BITS) + fat_offset; 
+   if (bdrv_pread (bs, off_bytes, 
+   (char *) &next_cluster, 
+   len) != len)   //从fat表读取簇号
+     return -1;
+
+   next_cluster = grub_le_to_cpu32 (next_cluster);
+   switch (data->fat_size)
+     {
+     case 16:
+       next_cluster &= 0xFFFF;
+       break;
+     case 12:
+       if (data->cur_cluster & 1)
+ next_cluster >>= 4;
+
+       next_cluster &= 0x0FFF;
+       break;
+     }
+
+   printf ("fat_size=%d, next_cluster=%u\n",
+ data->fat_size, next_cluster);
+
+   /* Check the end.  */
+   if (next_cluster >= data->cluster_eof_mark)
+     return ret;
+
+   if (next_cluster < 2 || next_cluster >= data->num_clusters)
+     {
+       printf("invalid cluster %u................\n",
+   next_cluster);
+       return -1;
+     }
+
+   data->cur_cluster = next_cluster;
+   data->cur_cluster_num++;
+ }
+
+      /* Read the data here.  */
+      //逻辑簇所对应的绝对扇区
+      sector = (data->cluster_sector
+ + ((data->cur_cluster - 2)
+    << (data->cluster_bits + data->logical_sector_bits))); 
+      //绝对扇区中去掉偏移后的字节数
+      size = (1 << logical_cluster_bits) - offset;
+      if (size > len)
+ size = len;
+
+      //disk->read_hook = read_hook;
+      //disk->closure = closure;
+      int64_t off_bytes = ((uint64_t)sector << GRUB_DISK_SECTOR_BITS) + offset;
+      //disk->read_hook = 0;
+      if (bdrv_pread (bs, off_bytes, buf, size) != size)
+ return -1;
+
+      len -= size;
+      buf += size;
+      ret += size;
+      logical_cluster++;
+      offset = 0;  //以后读的都是完整扇区
+    }
+
+  return ret;
+}
+
+//遍历由data->file_cluster指定的目录
+int
+grub_fat_iterate_dir (BlockDriverState *bs, struct grub_fat_data *data)
+{
+  struct grub_fat_dir_entry dir;
+  char *filename, *filep = 0;
+  grub_uint16_t *unibuf;
+  int slot = -1, slots = -1;
+  int checksum = -1;
+  grub_ssize_t offset = -sizeof(dir);
+
+  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
+    return printf("not a directory......\n");
+
+  /* Allocate space enough to hold a long name.  */
+  filename = (char*)malloc (0x40 * 13 * 4 + 1);
+  unibuf = (grub_uint16_t *) malloc (0x40 * 13 * 2);
+  if (! filename || ! unibuf)
+    {
+      free (filename);
+      free (unibuf);
+      return -1;
+    }
+
+
+  int count = 0;
+  while (1)
+    {
+      unsigned i;
+
+      /* Adjust the offset.  */
+      offset += sizeof (dir);
+      printf("[%d]offset=%u\n"
+      "data->cur_cluster_num=%u,data->cur_cluster=%u\n", 
+      count+1, offset, 
+      data->cur_cluster_num, data->cur_cluster);
+      /* Read a directory entry.  */
+      //0x0表示空目录
+      if ((grub_fat_read_data (bs, data, 0, 0,
+        offset, sizeof (dir), (char *) &dir)
+    != sizeof (dir) || dir.name[0] == 0))
+ {
+   printf("break...dir.name[0]==%d\n", dir.name[0]);
+   break;
+ }
+      /* Handle long name entries.  */
+      if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
+ {
+   printf("long name...\n");
+   struct grub_fat_long_name_entry *long_name
+     = (struct grub_fat_long_name_entry *) &dir;
+   grub_uint8_t id = long_name->id;
+
+   if (id & 0x40)  //the last item
+     {
+       id &= 0x3f;   //index or ordinal number  1~31
+       slots = slot = id;
+       checksum = long_name->checksum;
+       printf("the last ordinal num=%d!!!\n", id);
+     }
+
+   if (id != slot || slot == 0 || checksum != long_name->checksum)
+     {
+       printf("not valid ordinal number ,ignore...continue\n");
+       checksum = -1;
+       continue;
+     }
+
+   slot--;
+   memcpy (unibuf + slot * 13, long_name->name1, 5 * 2);
+   memcpy (unibuf + slot * 13 + 5, long_name->name2, 6 * 2);
+   memcpy (unibuf + slot * 13 + 11, long_name->name3, 2 * 2);
+   printf("memcpy...continue\n");
+   continue;
+ }
+
+      
+      /* Check if this entry is valid.  */
+      //oxe5表示已经被删除
+      if (dir.name[0] == 0xe5 || (dir.attr & ~GRUB_FAT_ATTR_VALID))
+ {
+   printf("dir.name[0]=0x%x, dir.attr=0x%x not valid...continue\n", 
+  dir.name[0], dir.attr);
+   continue;
+ }
+
+      printf("checksum=%d, slot=%d\n", checksum, slot);
+      /* This is a workaround for Japanese.  */
+      if (dir.name[0] == 0x05)
+ dir.name[0] = 0xe5;
+
+      if (checksum != -1 && slot == 0)
+ {
+   printf("checksuming\n");
+   grub_uint8_t sum;
+
+   for (sum = 0, i = 0; i < sizeof (dir.name); i++)
+     sum = ((sum >> 1) | (sum << 7)) + dir.name[i];
+
+   if (sum == checksum)
+     {//长名表项后面紧接短名表项,验证成功则证明真正是长名字
+       int u;
+
+       for (u = 0; u < slots * 13; u++)
+ unibuf[u] = grub_le_to_cpu16 (unibuf[u]);
+
+       *grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
+    slots * 13) = '\0';
+
+       //if (hook (filename, &dir, closure))
+         //break;
+
+       checksum = -1;
+       for (i = 0; i < sizeof (dir.name); i++)
+ printf("0x%x  ", dir.name[i]);
+       char *gbname = (char*)malloc(256);
+       u2g(filename, strlen(filename), gbname, 256);
+       printf("\ndir.name=%s, filename=%s, dir.attr=0x%x,"
+      "sum==checksum...continue\n",
+      dir.name, gbname, dir.attr);
+       free(gbname);
+       count++;
+       continue;
+     }
+
+   checksum = -1;
+ }
+
+      //后面的处理针对非真实长名和真实短名
+      /* Convert the 8.3 file name.  */
+      //去掉短名的空格,全改为小写
+      filep = filename;
+      if (dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
+ {
+   printf("VOLUME\n");
+   for (i = 0; i < sizeof (dir.name) && dir.name[i]
+  && ! grub_isspace (dir.name[i]); i++)
+     *filep++ = dir.name[i];
+ }
+      else
+ {
+   for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
+     *filep++ = grub_tolower (dir.name[i]);
+
+   *filep = '.';
+
+   for (i = 8; i < 11 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
+     *++filep = grub_tolower (dir.name[i]);
+
+   if (*filep != '.')
+     filep++;
+ }
+      *filep = '\0';
+
+      
+      for (i = 0; i < sizeof (dir.name); i++)
+ printf("0x%x  ", dir.name[i]);
+      printf("\ndir.name=%s, filename=【%s】, dir.attr=0x%x,"
+      "...next while\n",
+      dir.name, filename, dir.attr);
+      count++;
+      /*if(strcmp(filename, ".") && strcmp(filename, ".."))
+ {
+   printf("{==============>\n");
+   struct grub_fat_data *data2 = NULL;
+   data2 = (struct grub_fat_data*)malloc(sizeof(*data));
+   memcpy(data2, data, sizeof(*data));
+   data2->attr = dir.attr;
+   data2->file_size = grub_le_to_cpu32 (dir.file_size);
+   data2->file_cluster = ((grub_le_to_cpu16 (dir.first_cluster_high) << 16)
+  | grub_le_to_cpu16 (dir.first_cluster_low));
+   data2->cur_cluster_num = ~0U;
+   (grub_fat_iterate_dir(bs, data2) < 0) ? printf("error !!!!!!\n") : 0;
+   free(data2);
+   printf("<===================}\n");
+ }
+      */
+      //if (hook (filename, &dir, closure))
+        //break;
+    }
+
+  free (filename);
+  free (unibuf);
+
+  return 0;
+}
+
+
+/*
+struct grub_fat_find_dir_closure
+{
+  struct grub_fat_data *data;
+  int (*hook) (const char *filename,
+        const struct grub_dirhook_info *info,
+        void *closure);
+  void *closure;
+  char *dirname;
+  int call_hook;
+  int found;
+};
+
+
+static int
+grub_fat_find_dir_hook (const char *filename, struct grub_fat_dir_entry *dir,
+ void *closure)
+{
+  struct grub_fat_find_dir_closure *c = closure;
+  struct grub_dirhook_info info;
+  grub_memset (&info, 0, sizeof (info));
+
+  info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY);
+  info.case_insensitive = 1;
+
+  if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
+    return 0;
+  if (*(c->dirname) == '\0' && (c->call_hook))
+    return c->hook (filename, &info, c->closure);
+
+  if (grub_strcasecmp (c->dirname, filename) == 0)
+    {
+      struct grub_fat_data *data = "">
+
+      c->found = 1;
+      data->attr = dir->attr;
+      data->file_size = grub_le_to_cpu32 (dir->file_size);
+      data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16)
+        | grub_le_to_cpu16 (dir->first_cluster_low));
+      data->cur_cluster_num = ~0U;
+
+      if (c->call_hook)
+ c->hook (filename, &info, c->closure);
+
+      return 1;
+    }
+  return 0;
+}
+*/
+
+/* Find the underlying directory or file in PATH and return the
+   next path. If there is no next path or an error occurs, return NULL.
+   If HOOK is specified, call it with each file name.  */
+char *
+grub_fat_find_dir (BlockDriverState *bs, struct grub_fat_data *data,
+    const char *path,
+    int (*hook) (const char *filename,
+ const struct grub_dirhook_info *info,
+ void *closure),
+    void *closure)
+{
+  char *dirname, *dirp;
+  //struct grub_fat_find_dir_closure c;
+
+  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
+    {
+      printf("not a directory.............\n");
+      return 0;
+    }
+
+  /* Extract a directory name.  */
+  while (*path == '/')
+    path++;
+
+  dirp = grub_strchr (path, '/');
+  if (dirp)
+    {
+      unsigned len = dirp - path;
+
+      dirname = (char*)malloc (len + 1);
+      if (! dirname)
+ return 0;
+
+      memcpy (dirname, path, len);
+      dirname[len] = '\0';
+    }
+  else
+    {
+    /* This is actually a file.  */
+      dirname = grub_strdup (path);
+    }
+  //c.data = "">
+  //c.hook = hook;
+  //c.closure = closure;
+  //c.dirname =dirname;
+  //c.found = 0;
+  //c.call_hook = (! dirp && hook);
+  if(grub_fat_iterate_dir (bs, data)<0)
+    {
+       printf("file not found..\n");
+       return 0;
+    }
+    
+  
+  free (dirname);
+
+  return dirp;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/fat.h xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/fat.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/fat.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/fat.h 2012-12-28 16:02:41.009937738 +0800
@@ -0,0 +1,146 @@
+#ifndef FS_FAT_H
+#define FS_FAT_H
+
+
+#include "fs-types.h"
+#include "block_int.h"
+
+#define GRUB_DISK_SECTOR_BITS      9
+#define GRUB_FAT_DIR_ENTRY_SIZE 32
+
+#define GRUB_FAT_ATTR_READ_ONLY 0x01
+#define GRUB_FAT_ATTR_HIDDEN 0x02
+#define GRUB_FAT_ATTR_SYSTEM 0x04
+#define GRUB_FAT_ATTR_VOLUME_ID 0x08
+#define GRUB_FAT_ATTR_DIRECTORY 0x10
+#define GRUB_FAT_ATTR_ARCHIVE 0x20
+
+#define GRUB_FAT_MAXFILE 256
+
+#define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \
+  | GRUB_FAT_ATTR_HIDDEN \
+  | GRUB_FAT_ATTR_SYSTEM \
+  | GRUB_FAT_ATTR_VOLUME_ID)
+#define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \
+  | GRUB_FAT_ATTR_HIDDEN \
+  | GRUB_FAT_ATTR_SYSTEM \
+  | GRUB_FAT_ATTR_DIRECTORY \
+  | GRUB_FAT_ATTR_ARCHIVE \
+  | GRUB_FAT_ATTR_VOLUME_ID)
+
+struct grub_fat_bpb
+{
+  grub_uint8_t jmp_boot[3];
+  grub_uint8_t oem_name[8];
+  grub_uint16_t bytes_per_sector;
+  grub_uint8_t sectors_per_cluster;
+  grub_uint16_t num_reserved_sectors;
+  grub_uint8_t num_fats;
+  grub_uint16_t num_root_entries;
+  grub_uint16_t num_total_sectors_16;
+  grub_uint8_t media;
+  grub_uint16_t sectors_per_fat_16;
+  grub_uint16_t sectors_per_track;
+  grub_uint16_t num_heads;
+  grub_uint32_t num_hidden_sectors;
+  grub_uint32_t num_total_sectors_32;
+  union
+  {
+    struct
+    {
+      grub_uint8_t num_ph_drive;
+      grub_uint8_t reserved;
+      grub_uint8_t boot_sig;
+      grub_uint32_t num_serial;
+      grub_uint8_t label[11];
+      grub_uint8_t fstype[8];
+    } __attribute__ ((packed)) fat12_or_fat16;
+    struct
+    {
+      grub_uint32_t sectors_per_fat_32;
+      grub_uint16_t extended_flags;
+      grub_uint16_t fs_version;
+      grub_uint32_t root_cluster;
+      grub_uint16_t fs_info;
+      grub_uint16_t backup_boot_sector;
+      grub_uint8_t reserved[12];
+      grub_uint8_t num_ph_drive;
+      grub_uint8_t reserved1;
+      grub_uint8_t boot_sig;
+      grub_uint32_t num_serial;
+      grub_uint8_t label[11];
+      grub_uint8_t fstype[8];
+    } __attribute__ ((packed)) fat32;
+  } __attribute__ ((packed)) version_specific;
+} __attribute__ ((packed));
+
+struct grub_fat_dir_entry
+{
+  grub_uint8_t name[11];
+  grub_uint8_t attr;
+  grub_uint8_t nt_reserved;
+  grub_uint8_t c_time_tenth;
+  grub_uint16_t c_time;
+  grub_uint16_t c_date;
+  grub_uint16_t a_date;
+  grub_uint16_t first_cluster_high;
+  grub_uint16_t w_time;
+  grub_uint16_t w_date;
+  grub_uint16_t first_cluster_low;
+  grub_uint32_t file_size;
+} __attribute__ ((packed));
+
+struct grub_fat_long_name_entry
+{
+  grub_uint8_t id;
+  grub_uint16_t name1[5];
+  grub_uint8_t attr;
+  grub_uint8_t reserved;
+  grub_uint8_t checksum;
+  grub_uint16_t name2[6];
+  grub_uint16_t first_cluster;
+  grub_uint16_t name3[2];
+} __attribute__ ((packed));
+
+struct grub_fat_data
+{
+  int logical_sector_bits;
+  grub_uint32_t num_sectors;
+
+  grub_uint16_t fat_sector;
+  grub_uint32_t sectors_per_fat;
+  int fat_size;
+
+  grub_uint32_t root_cluster;
+  grub_uint32_t root_sector;
+  grub_uint32_t num_root_sectors;
+
+  int cluster_bits;
+  grub_uint32_t cluster_eof_mark;
+  grub_uint32_t cluster_sector;
+  grub_uint32_t num_clusters;
+
+  grub_uint8_t attr;
+  grub_ssize_t file_size;
+  grub_uint32_t file_cluster;
+  grub_uint32_t cur_cluster_num;
+  grub_uint32_t cur_cluster;
+
+  grub_uint32_t uuid;
+};
+
+
+
+
+
+
+struct grub_fat_data* grub_fat_mount (BlockDriverState *bs, uint32_t part_off_sector);
+int grub_fat_iterate_dir (BlockDriverState *bs, struct grub_fat_data *data);
+
+
+
+
+
+
+
+#endif
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/fs-types.h xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/fs-types.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/fs-types.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/fs-types.h 2012-12-28 16:02:41.009937738 +0800
@@ -0,0 +1,228 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_HEADER
+#define GRUB_TYPES_HEADER 1
+
+#include <config.h>
+#include <x86_64/types.h>
+
+#ifdef GRUB_UTIL
+# define GRUB_CPU_SIZEOF_VOID_P SIZEOF_VOID_P
+# define GRUB_CPU_SIZEOF_LONG SIZEOF_LONG
+# ifdef WORDS_BIGENDIAN
+#  define GRUB_CPU_WORDS_BIGENDIAN 1
+# else
+#  undef GRUB_CPU_WORDS_BIGENDIAN
+# endif
+#else /* ! GRUB_UTIL */
+# define GRUB_CPU_SIZEOF_VOID_P GRUB_TARGET_SIZEOF_VOID_P
+# define GRUB_CPU_SIZEOF_LONG GRUB_TARGET_SIZEOF_LONG
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define GRUB_CPU_WORDS_BIGENDIAN 1
+# else
+#  undef GRUB_CPU_WORDS_BIGENDIAN
+# endif
+#endif /* ! GRUB_UTIL */
+
+#if GRUB_CPU_SIZEOF_VOID_P != 4 && GRUB_CPU_SIZEOF_VOID_P != 8
+# error "This architecture is not supported because sizeof(void *) != 4 and sizeof(void *) != 8"
+#endif
+
+#ifndef GRUB_TARGET_WORDSIZE
+# if GRUB_TARGET_SIZEOF_VOID_P == 4
+#  define GRUB_TARGET_WORDSIZE 32
+# elif GRUB_TARGET_SIZEOF_VOID_P == 8
+#  define GRUB_TARGET_WORDSIZE 64
+# endif
+#endif
+
+/* Define various wide integers.  */
+typedef signed char grub_int8_t;
+typedef short grub_int16_t;
+typedef int grub_int32_t;
+#if GRUB_CPU_SIZEOF_LONG == 8
+typedef long grub_int64_t;
+#else
+typedef long long grub_int64_t;
+#endif
+
+typedef unsigned char grub_uint8_t;
+typedef unsigned short grub_uint16_t;
+typedef unsigned grub_uint32_t;
+#if GRUB_CPU_SIZEOF_LONG == 8
+typedef unsigned long grub_uint64_t;
+#else
+typedef unsigned long long grub_uint64_t;
+#endif
+
+/* Misc types.  */
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+typedef grub_uint64_t grub_target_addr_t;
+typedef grub_uint64_t grub_target_off_t;
+typedef grub_uint64_t grub_target_size_t;
+typedef grub_int64_t grub_target_ssize_t;
+#else
+typedef grub_uint32_t grub_target_addr_t;
+typedef grub_uint32_t grub_target_off_t;
+typedef grub_uint32_t grub_target_size_t;
+typedef grub_int32_t grub_target_ssize_t;
+#endif
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+typedef grub_uint64_t grub_addr_t;
+typedef grub_uint64_t grub_size_t;
+typedef grub_int64_t grub_ssize_t;
+#else
+typedef grub_uint32_t grub_addr_t;
+typedef grub_uint32_t grub_size_t;
+typedef grub_int32_t grub_ssize_t;
+#endif
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+# define GRUB_ULONG_MAX 18446744073709551615UL
+# define GRUB_LONG_MAX 9223372036854775807L
+# define GRUB_LONG_MIN (-9223372036854775807L - 1)
+#else
+# define GRUB_ULONG_MAX 4294967295UL
+# define GRUB_LONG_MAX 2147483647L
+# define GRUB_LONG_MIN (-2147483647L - 1)
+#endif
+
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+#define UINT_TO_PTR(x) ((void*)(grub_uint32_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(grub_uint32_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(x))
+#else
+#define UINT_TO_PTR(x) ((void*)(grub_uint64_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(grub_uint64_t)(x))
+#endif
+
+/* The type for representing a file offset.  */
+typedef grub_uint64_t grub_off_t;
+
+/* The type for representing a disk block address.  */
+typedef grub_uint64_t grub_disk_addr_t;
+
+/* Byte-orders.  */
+#define grub_swap_bytes16(x) \
+({ \
+   grub_uint16_t _x = (x); \
+   (grub_uint16_t) ((_x << 8) | (_x >> 8)); \
+})
+
+#if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) && defined(GRUB_TARGET_I386)
+static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x)
+{
+ return __builtin_bswap32(x);
+}
+
+static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
+{
+ return __builtin_bswap64(x);
+}
+#else /* not gcc 4.3 or newer */
+#define grub_swap_bytes32(x) \
+({ \
+   grub_uint32_t _x = (x); \
+   (grub_uint32_t) ((_x << 24) \
+                    | ((_x & (grub_uint32_t) 0xFF00UL) << 8) \
+                    | ((_x & (grub_uint32_t) 0xFF0000UL) >> 8) \
+                    | (_x >> 24)); \
+})
+
+#define grub_swap_bytes64(x) \
+({ \
+   grub_uint64_t _x = (x); \
+   (grub_uint64_t) ((_x << 56) \
+                    | ((_x & (grub_uint64_t) 0xFF00ULL) << 40) \
+                    | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) \
+                    | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) \
+                    | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) \
+                    | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) \
+                    | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) \
+                    | (_x >> 56)); \
+})
+#endif /* not gcc 4.3 or newer */
+
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+# define grub_cpu_to_le16(x) grub_swap_bytes16(x)
+# define grub_cpu_to_le32(x) grub_swap_bytes32(x)
+# define grub_cpu_to_le64(x) grub_swap_bytes64(x)
+# define grub_le_to_cpu16(x) grub_swap_bytes16(x)
+# define grub_le_to_cpu32(x) grub_swap_bytes32(x)
+# define grub_le_to_cpu64(x) grub_swap_bytes64(x)
+# define grub_cpu_to_be16(x) ((grub_uint16_t) (x))
+# define grub_cpu_to_be32(x) ((grub_uint32_t) (x))
+# define grub_cpu_to_be64(x) ((grub_uint64_t) (x))
+# define grub_be_to_cpu16(x) ((grub_uint16_t) (x))
+# define grub_be_to_cpu32(x) ((grub_uint32_t) (x))
+# define grub_be_to_cpu64(x) ((grub_uint64_t) (x))
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define grub_target_to_host16(x) ((grub_uint16_t) (x))
+#  define grub_target_to_host32(x) ((grub_uint32_t) (x))
+#  define grub_target_to_host64(x) ((grub_uint64_t) (x))
+#  define grub_host_to_target16(x) ((grub_uint16_t) (x))
+#  define grub_host_to_target32(x) ((grub_uint32_t) (x))
+#  define grub_host_to_target64(x) ((grub_uint64_t) (x))
+# else /* ! GRUB_TARGET_WORDS_BIGENDIAN */
+#  define grub_target_to_host16(x) grub_swap_bytes16(x)
+#  define grub_target_to_host32(x) grub_swap_bytes32(x)
+#  define grub_target_to_host64(x) grub_swap_bytes64(x)
+#  define grub_host_to_target16(x) grub_swap_bytes16(x)
+#  define grub_host_to_target32(x) grub_swap_bytes32(x)
+#  define grub_host_to_target64(x) grub_swap_bytes64(x)
+# endif
+#else /* ! WORDS_BIGENDIAN */
+# define grub_cpu_to_le16(x) ((grub_uint16_t) (x))
+# define grub_cpu_to_le32(x) ((grub_uint32_t) (x))
+# define grub_cpu_to_le64(x) ((grub_uint64_t) (x))
+# define grub_le_to_cpu16(x) ((grub_uint16_t) (x))
+# define grub_le_to_cpu32(x) ((grub_uint32_t) (x))
+# define grub_le_to_cpu64(x) ((grub_uint64_t) (x))
+# define grub_cpu_to_be16(x) grub_swap_bytes16(x)
+# define grub_cpu_to_be32(x) grub_swap_bytes32(x)
+# define grub_cpu_to_be64(x) grub_swap_bytes64(x)
+# define grub_be_to_cpu16(x) grub_swap_bytes16(x)
+# define grub_be_to_cpu32(x) grub_swap_bytes32(x)
+# define grub_be_to_cpu64(x) grub_swap_bytes64(x)
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define grub_target_to_host16(x) grub_swap_bytes16(x)
+#  define grub_target_to_host32(x) grub_swap_bytes32(x)
+#  define grub_target_to_host64(x) grub_swap_bytes64(x)
+#  define grub_host_to_target16(x) grub_swap_bytes16(x)
+#  define grub_host_to_target32(x) grub_swap_bytes32(x)
+#  define grub_host_to_target64(x) grub_swap_bytes64(x)
+# else /* ! GRUB_TARGET_WORDS_BIGENDIAN */
+#  define grub_target_to_host16(x) ((grub_uint16_t) (x))
+#  define grub_target_to_host32(x) ((grub_uint32_t) (x))
+#  define grub_target_to_host64(x) ((grub_uint64_t) (x))
+#  define grub_host_to_target16(x) ((grub_uint16_t) (x))
+#  define grub_host_to_target32(x) ((grub_uint32_t) (x))
+#  define grub_host_to_target64(x) ((grub_uint64_t) (x))
+# endif
+#endif /* ! WORDS_BIGENDIAN */
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+#  define grub_host_to_target_addr(x) grub_host_to_target64(x)
+#else
+#  define grub_host_to_target_addr(x) grub_host_to_target32(x)
+#endif
+
+#endif /* ! GRUB_TYPES_HEADER */
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/i386/types.h xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/i386/types.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/i386/types.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/i386/types.h 2012-12-28 16:02:41.010937619 +0800
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2006,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER 1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P 4
+
+/* The size of long.  */
+#define GRUB_TARGET_SIZEOF_LONG 4
+
+/* i386 is little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#define GRUB_TARGET_I386 1
+
+#define GRUB_TARGET_MIN_ALIGN 1
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/misc.h xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/misc.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/misc.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/misc.h 2012-12-28 16:02:41.010937619 +0800
@@ -0,0 +1,17 @@
+int
+grub_strncmp (const char *s1, const char *s2, grub_size_t n)
+{
+  if (n == 0)
+    return 0;
+
+  while (*s1 && *s2 && --n)
+    {
+      if (*s1 != *s2)
+        break;
+
+      s1++;
+      s2++;
+    }
+
+  return (int) *s1 - (int) *s2;
+}
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/x86_64/types.h xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/x86_64/types.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/x86_64/types.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/x86_64/types.h 2012-12-28 16:02:41.011764159 +0800
@@ -0,0 +1,39 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER 1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P 8
+
+/* The size of long.  */
+#ifdef __MINGW32__
+#define GRUB_TARGET_SIZEOF_LONG 4
+#else
+#define GRUB_TARGET_SIZEOF_LONG 8
+#endif
+
+/* x86_64 is little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#define GRUB_TARGET_X86_64 1
+
+#define GRUB_TARGET_MIN_ALIGN 1
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/i386/types.h xen-4.1.2-b/tools/ioemu-qemu-xen/i386/types.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/i386/types.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/i386/types.h 2012-12-28 16:02:41.017802371 +0800
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2006,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER 1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P 4
+
+/* The size of long.  */
+#define GRUB_TARGET_SIZEOF_LONG 4
+
+/* i386 is little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#define GRUB_TARGET_I386 1
+
+#define GRUB_TARGET_MIN_ALIGN 1
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/Makefile xen-4.1.2-b/tools/ioemu-qemu-xen/Makefile
--- xen-4.1.2-a/tools/ioemu-qemu-xen/Makefile 2011-02-12 01:54:51.000000000 +0800
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/Makefile 2012-12-28 16:02:41.011764159 +0800
@@ -188,17 +188,18 @@ libqemu_common.a: $(OBJS)
 #######################################################################
 # USER_OBJS is code used by qemu userspace emulation
 USER_OBJS=cutils.o  cache-utils.o
 
 libqemu_user.a: $(USER_OBJS)
 
 ######################################################################
 
-qemu-img$(EXESUF): qemu-img.o qemu-tool.o osdep.o $(BLOCK_OBJS)
+
+qemu-img$(EXESUF):fs-time.o grub_err.o partition.o fshelp.o ntfs.o fat.o misc.o debug.o qemu-img.o qemu-tool.o osdep.o $(BLOCK_OBJS)
 
 qemu-nbd$(EXESUF):  qemu-nbd.o qemu-tool.o osdep.o $(BLOCK_OBJS)
 
 qemu-img$(EXESUF) qemu-nbd$(EXESUF): LIBS += -lz
 
 
 clean:
 # avoid old build problems by removing potentially incorrect old files
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/Makefile.orig xen-4.1.2-b/tools/ioemu-qemu-xen/Makefile.orig
--- xen-4.1.2-a/tools/ioemu-qemu-xen/Makefile.orig 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/Makefile.orig 2012-12-28 15:59:35.354681634 +0800
@@ -0,0 +1,372 @@
+# Makefile for QEMU.
+
+include config-host.mak
+include $(SRC_PATH)/rules.mak
+
+.PHONY: all clean cscope distclean dvi html info install install-doc \
+ recurse-all speed tar tarbin test
+
+VPATH=$(SRC_PATH):$(SRC_PATH)/hw
+
+
+CFLAGS += $(OS_CFLAGS) $(ARCH_CFLAGS)
+LDFLAGS += $(OS_LDFLAGS) $(ARCH_LDFLAGS)
+
+CPPFLAGS += -I. -I$(SRC_PATH) -MMD -MP -MT $@
+CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+LIBS=
+ifdef CONFIG_STATIC
+LDFLAGS += -static
+endif
+ifdef BUILD_DOCS
+DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8
+else
+DOCS=
+endif
+
+LIBS+=$(AIOLIBS)
+
+ifdef CONFIG_SOLARIS
+LIBS+=-lsocket -lnsl -lresolv
+endif
+
+ifdef CONFIG_WIN32
+LIBS+=-lwinmm -lws2_32 -liphlpapi
+endif
+
+all: $(TOOLS) $(DOCS) recurse-all
+
+SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
+
+subdir-%:
+ $(call quiet-command,$(MAKE) -C $* V="$(V)" TARGET_DIR="$*/" all,)
+
+$(filter %-softmmu,$(SUBDIR_RULES)): libqemu_common.a
+$(filter %-user,$(SUBDIR_RULES)): libqemu_user.a
+
+recurse-all: $(SUBDIR_RULES)
+
+CPPFLAGS += -I$(XEN_ROOT)/tools/libxc
+CPPFLAGS += -I$(XEN_ROOT)/tools/blktap/lib
+CPPFLAGS += -I$(XEN_ROOT)/tools/xenstore
+CPPFLAGS += -I$(XEN_ROOT)/tools/include
+
+tapdisk-ioemu: tapdisk-ioemu.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c hw/xen_blktap.c osdep.c
+ $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
+
+#######################################################################
+# BLOCK_OBJS is code used by both qemu system emulation and qemu-img
+
+BLOCK_OBJS=cutils.o osdep.o qemu-malloc.o
+BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
+BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
+BLOCK_OBJS+=block-qcow2.o block-parallels.o block-nbd.o
+BLOCK_OBJS+=nbd.o block.o aio.o
+
+ifdef CONFIG_WIN32
+BLOCK_OBJS += block-raw-win32.o
+else
+ifdef CONFIG_AIO
+BLOCK_OBJS += posix-aio-compat.o
+endif
+BLOCK_OBJS += block-raw-posix.o
+endif
+
+######################################################################
+# libqemu_common.a: Target independent part of system emulation. The
+# long term path is to suppress *all* target specific code in case of
+# system emulation, i.e. a single QEMU executable should support all
+# CPUs and machines.
+
+OBJS=$(BLOCK_OBJS)
+OBJS+=readline.o console.o
+
+OBJS+=irq.o
+OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o
+OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o
+OBJS+=tmp105.o lm832x.o
+OBJS+=scsi-disk.o cdrom.o
+OBJS+=scsi-generic.o
+OBJS+=usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
+OBJS+=usb-serial.o usb-net.o
+OBJS+=sd.o ssi-sd.o
+OBJS+=bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
+OBJS+=buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
+OBJS+=qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o
+
+ifdef CONFIG_BRLAPI
+OBJS+= baum.o
+LIBS+=-lbrlapi
+endif
+
+ifdef CONFIG_WIN32
+OBJS+=tap-win32.o
+else
+OBJS+=migration-exec.o
+endif
+
+AUDIO_OBJS = audio.o noaudio.o wavaudio.o mixeng.o
+ifdef CONFIG_SDL
+AUDIO_OBJS += sdlaudio.o
+endif
+ifdef CONFIG_OSS
+AUDIO_OBJS += ossaudio.o
+endif
+ifdef CONFIG_COREAUDIO
+AUDIO_OBJS += coreaudio.o
+AUDIO_PT = yes
+endif
+ifdef CONFIG_ALSA
+AUDIO_OBJS += alsaaudio.o
+endif
+ifdef CONFIG_DSOUND
+AUDIO_OBJS += dsoundaudio.o
+endif
+ifdef CONFIG_FMOD
+AUDIO_OBJS += fmodaudio.o
+audio/audio.o audio/fmodaudio.o: CPPFLAGS := -I$(CONFIG_FMOD_INC) $(CPPFLAGS)
+endif
+ifdef CONFIG_ESD
+AUDIO_PT = yes
+AUDIO_PT_INT = yes
+AUDIO_OBJS += esdaudio.o
+endif
+ifdef CONFIG_PA
+AUDIO_PT = yes
+AUDIO_PT_INT = yes
+AUDIO_OBJS += paaudio.o
+endif
+ifdef AUDIO_PT
+LDFLAGS += -pthread
+endif
+ifdef AUDIO_PT_INT
+AUDIO_OBJS += audio_pt_int.o
+endif
+AUDIO_OBJS+= wavcapture.o
+ifdef CONFIG_AUDIO
+OBJS+=$(addprefix audio/, $(AUDIO_OBJS))
+endif
+
+ifdef CONFIG_SDL
+OBJS+=sdl.o x_keymap.o
+endif
+ifdef CONFIG_CURSES
+OBJS+=curses.o
+endif
+OBJS+=vnc.o d3des.o
+
+ifdef CONFIG_COCOA
+OBJS+=cocoa.o
+endif
+
+ifdef CONFIG_SLIRP
+CPPFLAGS+=-I$(SRC_PATH)/slirp
+SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
+slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
+tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
+OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
+endif
+
+LIBS+=$(VDE_LIBS)
+
+cocoa.o: cocoa.m
+
+sdl.o: sdl.c keymaps.c sdl_keysym.h
+
+sdl.o audio/sdlaudio.o: CFLAGS += $(SDL_CFLAGS)
+
+vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h d3des.c d3des.h
+
+vnc.o: CFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
+
+curses.o: curses.c keymaps.c curses_keys.h
+
+bt-host.o: CFLAGS += $(CONFIG_BLUEZ_CFLAGS)
+
+libqemu_common.a: $(OBJS)
+
+#######################################################################
+# USER_OBJS is code used by qemu userspace emulation
+USER_OBJS=cutils.o  cache-utils.o
+
+libqemu_user.a: $(USER_OBJS)
+
+######################################################################
+
+qemu-img$(EXESUF): qemu-img.o qemu-tool.o osdep.o $(BLOCK_OBJS)
+
+qemu-nbd$(EXESUF):  qemu-nbd.o qemu-tool.o osdep.o $(BLOCK_OBJS)
+
+qemu-img$(EXESUF) qemu-nbd$(EXESUF): LIBS += -lz
+
+
+clean:
+# avoid old build problems by removing potentially incorrect old files
+ rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
+ rm -f *.o .*.d *.a $(TOOLS) TAGS cscope.* *.pod *~ */*~
+ rm -f slirp/*.o slirp/.*.d audio/*.o audio/.*.d
+ $(MAKE) -C tests clean
+ for d in $(TARGET_DIRS); do \
+ $(MAKE) -C $$d $@ || exit 1 ; \
+        done
+
+distclean: clean
+ rm -f config-host.mak config-host.h $(DOCS)
+ rm -f qemu-{doc,tech}.{info,aux,cp,dvi,fn,info,ky,log,pg,toc,tp,vr}
+ for d in $(TARGET_DIRS); do \
+ rm -rf $$d || exit 1 ; \
+        done
+
+KEYMAPS=da     en-gb  et  fr     fr-ch  is  lt  modifiers  no  pt-br  sv \
+ar      de     en-us  fi  fr-be  hr     it  lv  nl         pl  ru     th \
+common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr
+
+ifdef INSTALL_BLOBS
+BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
+video.x openbios-sparc32 openbios-sparc64 openbios-ppc \
+pxe-ne2k_pci.bin pxe-rtl8139.bin pxe-pcnet.bin pxe-e1000.bin \
+bamboo.dtb
+else
+BLOBS=
+endif
+
+install-doc: $(DOCS)
+ mkdir -p "$(DESTDIR)$(docdir)"
+ $(INSTALL) -m 644 qemu-doc.html  qemu-tech.html "$(DESTDIR)$(docdir)"
+ifndef CONFIG_WIN32
+ mkdir -p "$(DESTDIR)$(mandir)/man1"
+ $(INSTALL) -m 644 qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
+ mkdir -p "$(DESTDIR)$(mandir)/man8"
+ $(INSTALL) -m 644 qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
+endif
+
+install: all $(if $(BUILD_DOCS),install-doc)
+ mkdir -p "$(DESTDIR)$(bindir)"
+ifneq ($(TOOLS),)
+ $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
+endif
+ifneq ($(BLOBS),)
+ mkdir -p "$(DESTDIR)$(datadir)"
+ set -e; for x in $(BLOBS); do \
+ $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
+ done
+endif
+ifndef CONFIG_WIN32
+ mkdir -p "$(DESTDIR)$(datadir)/keymaps"
+ set -e; for x in $(KEYMAPS); do \
+ $(INSTALL) -m 644 $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
+ done
+endif
+ for d in $(TARGET_DIRS); do \
+ $(MAKE) -C $$d $@ || exit 1 ; \
+        done
+
+# various test targets
+test speed: all
+ $(MAKE) -C tests $@
+
+TAGS:
+ etags *.[ch] tests/*.[ch]
+
+cscope:
+ rm -f ./cscope.*
+ find . -name "*.[ch]" -print | sed 's,^\./,,' > ./cscope.files
+ cscope -b
+
+# documentation
+%.html: %.texi
+ texi2html -monolithic -number $<
+
+%.info: %.texi
+ makeinfo $< -o $@
+
+%.dvi: %.texi
+ texi2dvi $<
+
+qemu.1: qemu-doc.texi
+ $(SRC_PATH)/texi2pod.pl $< qemu.pod
+ pod2man --section=1 --center=" " --release=" " qemu.pod > $@
+
+qemu-img.1: qemu-img.texi
+ $(SRC_PATH)/texi2pod.pl $< qemu-img.pod
+ pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@
+
+qemu-nbd.8: qemu-nbd.texi
+ $(SRC_PATH)/texi2pod.pl $< qemu-nbd.pod
+ pod2man --section=8 --center=" " --release=" " qemu-nbd.pod > $@
+
+
+dvi: qemu-doc.dvi qemu-tech.dvi
+
+html: qemu-doc.html qemu-tech.html
+
+qemu-doc.dvi qemu-doc.html qemu-doc.info: qemu-img.texi qemu-nbd.texi
+
+VERSION ?= $(shell cat VERSION)
+FILE = qemu-$(VERSION)
+
+# tar release (use 'make -k tar' on a checkouted tree)
+tar:
+ rm -rf /tmp/$(FILE)
+ cp -r . /tmp/$(FILE)
+ cd /tmp && tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS --exclude .git --exclude .svn
+ rm -rf /tmp/$(FILE)
+
+# generate a binary distribution
+tarbin:
+ cd / && tar zcvf ~/qemu-$(VERSION)-$(ARCH).tar.gz \
+ $(bindir)/qemu \
+ $(bindir)/qemu-system-x86_64 \
+ $(bindir)/qemu-system-arm \
+ $(bindir)/qemu-system-cris \
+ $(bindir)/qemu-system-m68k \
+ $(bindir)/qemu-system-mips \
+ $(bindir)/qemu-system-mipsel \
+ $(bindir)/qemu-system-mips64 \
+ $(bindir)/qemu-system-mips64el \
+ $(bindir)/qemu-system-ppc \
+ $(bindir)/qemu-system-ppcemb \
+ $(bindir)/qemu-system-ppc64 \
+ $(bindir)/qemu-system-sh4 \
+ $(bindir)/qemu-system-sh4eb \
+ $(bindir)/qemu-system-sparc \
+ $(bindir)/qemu-i386 \
+ $(bindir)/qemu-x86_64 \
+ $(bindir)/qemu-alpha \
+ $(bindir)/qemu-arm \
+ $(bindir)/qemu-armeb \
+ $(bindir)/qemu-cris \
+ $(bindir)/qemu-m68k \
+ $(bindir)/qemu-mips \
+ $(bindir)/qemu-mipsel \
+ $(bindir)/qemu-ppc \
+ $(bindir)/qemu-ppc64 \
+ $(bindir)/qemu-ppc64abi32 \
+ $(bindir)/qemu-sh4 \
+ $(bindir)/qemu-sh4eb \
+ $(bindir)/qemu-sparc \
+ $(bindir)/qemu-sparc64 \
+ $(bindir)/qemu-sparc32plus \
+ $(bindir)/qemu-img \
+ $(bindir)/qemu-nbd \
+ $(datadir)/bios.bin \
+ $(datadir)/vgabios.bin \
+ $(datadir)/vgabios-cirrus.bin \
+ $(datadir)/ppc_rom.bin \
+ $(datadir)/video.x \
+ $(datadir)/openbios-sparc32 \
+ $(datadir)/openbios-sparc64 \
+ $(datadir)/openbios-ppc \
+ $(datadir)/pxe-ne2k_pci.bin \
+ $(datadir)/pxe-rtl8139.bin \
+ $(datadir)/pxe-pcnet.bin \
+ $(datadir)/pxe-e1000.bin \
+ $(docdir)/qemu-doc.html \
+ $(docdir)/qemu-tech.html \
+ $(mandir)/man1/qemu.1 \
+ $(mandir)/man1/qemu-img.1 \
+ $(mandir)/man8/qemu-nbd.8
+
+# Include automatically generated dependency files
+-include $(wildcard .*.d audio/.*.d slirp/.*.d)
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/misc.c xen-4.1.2-b/tools/ioemu-qemu-xen/misc.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/misc.c 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/misc.c 2012-12-28 16:02:41.012937846 +0800
@@ -0,0 +1,432 @@
+#include "misc.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "grub_err.h"
+
+
+int
+grub_isspace (int c)
+{
+  return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
+}
+
+int
+grub_tolower (int c)
+{
+  if (c >= 'A' && c <= 'Z')
+    return c - 'A' + 'a';
+
+  return c;
+}
+
+
+char *
+grub_strchr (const char *s, int c)
+{
+  do
+    {
+      if (*s == c)
+ return (char *) s;
+    }
+  while (*s++);
+
+  return 0;
+}
+
+
+grub_size_t
+grub_strlen (const char *s)
+{
+  const char *p = s;
+
+  while (*p)
+    p++;
+
+  return p - s;
+}
+
+
+
+
+
+char *
+grub_strncpy (char *dest, const char *src, int c)
+{
+  char *p = dest;
+
+  while ((*p++ = *src++) != '\0' && --c)
+    ;
+
+  return dest;
+}
+
+char *
+grub_strdup (const char *s)
+{
+  grub_size_t len;
+  char *p;
+
+  len = grub_strlen (s) + 1;
+  p = (char *) malloc (len);
+  if (! p)
+    return 0;
+
+  return memcpy (p, s, len);
+}
+
+
+
+char *
+grub_strndup (const char *s, grub_size_t n)
+{
+  grub_size_t len;
+  char *p;
+
+  len = grub_strlen (s);
+  if (len > n)
+    len = n;
+  p = (char *) malloc (len + 1);
+  if (! p)
+    return 0;
+
+  memcpy (p, s, len);
+  p[len] = '\0';
+  return p;
+}
+
+
+
+
+int
+grub_strcmp (const char *s1, const char *s2)
+{
+  while (*s1 && *s2)
+    {
+      if (*s1 != *s2)
+ break;
+
+      s1++;
+      s2++;
+    }
+
+  return (int) *s1 - (int) *s2;
+}
+
+int
+grub_strncmp (const char *s1, const char *s2, grub_size_t n)
+{
+  if (n == 0)
+    return 0;
+
+  while (*s1 && *s2 && --n)
+    {
+      if (*s1 != *s2)
+ break;
+
+      s1++;
+      s2++;
+    }
+
+  return (int) *s1 - (int) *s2;
+}
+
+
+int
+grub_strcasecmp (const char *s1, const char *s2)
+{
+  while (*s1 && *s2)
+    {
+      if (grub_tolower (*s1) != grub_tolower (*s2))
+ break;
+
+      s1++;
+      s2++;
+    }
+
+  return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
+}
+
+
+int
+grub_strncasecmp (const char *s1, const char *s2, grub_size_t n)
+{
+  if (n == 0)
+    return 0;
+
+  while (*s1 && *s2 && --n)
+    {
+      if (grub_tolower (*s1) != grub_tolower (*s2))
+ break;
+
+      s1++;
+      s2++;
+    }
+
+  return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
+}
+
+void *
+grub_memmove (void *dest, const void *src, grub_size_t n)
+{
+  char *d = (char *) dest;
+  const char *s = (const char *) src;
+
+  if (d < s)
+    while (n--)
+      *d++ = *s++;
+  else
+    {
+      d += n;
+      s += n;
+
+      while (n--)
+ *--d = *--s;
+    }
+
+  return dest;
+}
+
+
+void *
+grub_malloc (grub_size_t size)
+{
+  void *ret;
+  ret = malloc (size);
+  if (!ret)
+    grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+  return ret;
+}
+
+
+
+void
+grub_free (void *ptr)
+{
+  free (ptr);
+}
+
+
+void *
+grub_memset (void *s, int c, grub_size_t n)
+{
+  unsigned char *p = (unsigned char *) s;
+
+  while (n--)
+    *p++ = (unsigned char) c;
+
+  return s;
+}
+
+int
+grub_memcmp (const void *s1, const void *s2, grub_size_t n)
+{
+  const char *t1 = s1;
+  const char *t2 = s2;
+
+  while (n--)
+    {
+      if (*t1 != *t2)
+ return (int) *t1 - (int) *t2;
+
+      t1++;
+      t2++;
+    }
+
+  return 0;
+}
+
+
+void *
+grub_zalloc (grub_size_t size)
+{
+  void *ret;
+
+  ret = grub_malloc (size);
+  if (!ret)
+    return NULL;
+  memset (ret, 0, size);
+  return ret;
+}
+
+/* Divide N by D, return the quotient, and store the remainder in *R.  */
+grub_uint64_t
+grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
+{
+  /* This algorithm is typically implemented by hardware. The idea
+     is to get the highest bit in N, 64 times, by keeping
+     upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
+     represents the high 64 bits in 128-bits space.  */
+  unsigned bits = 64;
+  unsigned long long q = 0;
+  unsigned m = 0;
+
+  /* Skip the slow computation if 32-bit arithmetic is possible.  */
+  if (n < 0xffffffff)
+    {
+      if (r)
+ *r = ((grub_uint32_t) n) % d;
+
+      return ((grub_uint32_t) n) / d;
+    }
+
+  while (bits--)
+    {
+      m <<= 1;
+
+      if (n & (1ULL << 63))
+ m |= 1;
+
+      q <<= 1;
+      n <<= 1;
+
+      if (m >= d)
+ {
+   q |= 1;
+   m -= d;
+ }
+    }
+
+  if (r)
+    *r = m;
+
+  return q;
+}
+
+
+
+/* Convert UTF-16 to UTF-8.  */
+grub_uint8_t *
+grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
+                    grub_size_t size)
+{
+  grub_uint32_t code_high = 0;
+
+  while (size--)
+    {
+      grub_uint32_t code = *src++;
+
+      if (code_high)
+        {
+          if (code >= 0xDC00 && code <= 0xDFFF)
+            {
+              /* Surrogate pair.  */
+              code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
+
+              *dest++ = (code >> 18) | 0xF0;
+              *dest++ = ((code >> 12) & 0x3F) | 0x80;
+              *dest++ = ((code >> 6) & 0x3F) | 0x80;
+              *dest++ = (code & 0x3F) | 0x80;
+            }
+          else
+            {
+              /* Error...  */
+              *dest++ = '?';
+            }
+
+          code_high = 0;
+        }
+      else
+        {
+          if (code <= 0x007F)
+            *dest++ = code;
+          else if (code <= 0x07FF)
+            {
+              *dest++ = (code >> 6) | 0xC0;
+              *dest++ = (code & 0x3F) | 0x80;
+            }
+          else if (code >= 0xD800 && code <= 0xDBFF)
+            {
+              code_high = code;
+              continue;
+            }
+          else if (code >= 0xDC00 && code <= 0xDFFF)
+            {
+              /* Error... */
+              *dest++ = '?';
+            }
+          else
+            {
+              *dest++ = (code >> 12) | 0xE0;
+              *dest++ = ((code >> 6) & 0x3F) | 0x80;
+              *dest++ = (code & 0x3F) | 0x80;
+            }
+        }
+    }
+
+  return dest;
+}
+
+
+
+
+
+
+static void print_byte(char *p, int len)
+{
+  printf("\n****************start print %s********************\n", p);
+  int i;
+  unsigned char *pb = (unsigned char*)p;
+  for(i = 0; i < len; i++)
+    {
+      printf("0x%02x,", pb[i]);
+    }
+  printf("\n**********************end**************************\n");
+}
+
+
+
+#include   <iconv.h> 
+#define   OUTLEN   256 
+
+
+//代码转换:从一种编码转为另一种编码 
+static int   code_convert(const char   *from_charset, const char   *to_charset, 
+     char   *inbuf, size_t   inlen,
+    char   *outbuf, size_t   outlen) 
+{ 
+  iconv_t   cd; 
+  int   rc; 
+  char   **pin   =   &inbuf; 
+  char   **pout   =   &outbuf; 
+
+  //printf("sizeof(int)=%d, sizeof(size_t)=%d\n", sizeof(int), sizeof(size_t));
+  cd   =   iconv_open(to_charset, from_charset); 
+  if   (cd==0)   return   -1; 
+  memset(outbuf, 0, outlen); 
+  if   (iconv(cd, pin, &inlen, pout, &outlen)==-1)   return   -1; 
+  iconv_close(cd); 
+  return   0; 
+} 
+//UNICODE码转为GB2312码 
+int   u2g(char   *inbuf, size_t   inlen, char   *outbuf, size_t  outlen) 
+{
+  return   code_convert("utf-8", "gb2312", inbuf, inlen, outbuf, outlen); 
+} 
+//GB2312码转为UNICODE码 
+int   g2u(char   *inbuf, size_t   inlen, char   *outbuf, size_t   outlen) 
+{ 
+  return   code_convert("gb2312", "utf-8", inbuf, inlen, outbuf, outlen); 
+} 
+
+
+
+void test(void) 
+{
+  //字符编码转换=锘垮?绗????浆??
+  char   in_utf8[]   =   {0xe5,0xad,0x97,0xe7,0xac,0xa6,0xe7,0xbc,0x96,0xe7,0xa0,0x81,0xe8,0xbd,0xac,0xe6,0x8d,0xa2}; 
+  char   *in_gb2312   = (char*)  "字符编码转换"; 
+  char   out[OUTLEN]; 
+  int rc;
+  //utf8码转为gb2312码 
+  rc   =   u2g(in_utf8, strlen(in_utf8), out, OUTLEN); 
+  printf("utf8-->gb2312   out=%s\n", out);
+  print_byte(out, strlen(out));
+  //gb2312码转为utf8码 
+  rc   =   g2u(in_gb2312, strlen(in_gb2312), out, OUTLEN); 
+  print_byte(out, strlen(out));
+  printf("gb2312-->utf8   out=%s\n",out); 
+} 
+
+
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/misc.h xen-4.1.2-b/tools/ioemu-qemu-xen/misc.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/misc.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/misc.h 2012-12-28 16:02:41.012937846 +0800
@@ -0,0 +1,89 @@
+#include "fs-types.h"
+#include <stddef.h>
+
+
+
+
+
+#define grub_memcpy(d,s,n)grub_memmove ((d), (s), (n))
+
+
+int
+grub_isspace (int c);
+
+int
+grub_tolower (int c);
+
+
+char *
+grub_strchr (const char *s, int c);
+
+
+grub_size_t
+grub_strlen (const char *s);
+
+
+
+char *
+grub_strdup (const char *s);
+
+
+
+char *
+grub_strndup (const char *s, grub_size_t n);
+
+
+char *
+grub_strncpy (char *dest, const char *src, int c);
+
+
+int
+grub_strcmp (const char *s1, const char *s2);
+
+int
+grub_strncmp (const char *s1, const char *s2, grub_size_t n);
+
+int
+grub_strcasecmp (const char *s1, const char *s2);
+
+int
+grub_strncasecmp (const char *s1, const char *s2, grub_size_t n);
+
+void *
+grub_memmove (void *dest, const void *src, grub_size_t n);
+
+int
+grub_memcmp (const void *s1, const void *s2, grub_size_t n);
+
+void *
+grub_malloc (grub_size_t size);
+
+void *
+grub_memset (void *s, int c, grub_size_t n);
+
+void
+grub_free (void *ptr);
+
+void *
+grub_zalloc (grub_size_t size);
+
+grub_uint64_t
+grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r);
+
+/* Convert UTF-16 to UTF-8.  */
+grub_uint8_t *
+grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
+                    grub_size_t size);
+
+
+//UNICODE码转为GB2312码 
+int   u2g(char   *inbuf, size_t   inlen, char   *outbuf, size_t   outlen);
+//GB2312码转为UNICODE码 
+int   g2u(char   *inbuf, size_t   inlen, char   *outbuf, size_t   outlen);
+
+
+
+void test(void);
+
+
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/ntfs.c xen-4.1.2-b/tools/ioemu-qemu-xen/ntfs.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/ntfs.c 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/ntfs.c 2012-12-28 16:02:41.013937038 +0800
@@ -0,0 +1,1188 @@
+/* ntfs.c - NTFS filesystem */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "misc.h"
+#include "fshelp.h"
+#include "ntfs.h"
+#include "debug.h"
+#include "grub_err.h"
+#include "err.h"
+
+#define GRUB_DISK_SECTOR_SIZE 0x200
+ntfscomp_func_t grub_ntfscomp_func;
+
+//important
+//lcn is relative to start sector of the volume
+static grub_off_t s_part_off_sector;
+static grub_uint32_t s_bpb_bytes_per_sector;
+int bdrv_pread_from_lcn_of_volum(BlockDriverState *bs, int64_t offset,
+  void *buf1, int count1)
+{
+  return bdrv_pread(bs, s_part_off_sector * s_bpb_bytes_per_sector + offset,
+  buf1, count1);
+}
+
+
+static grub_err_t
+fixup (struct grub_ntfs_data *data, char *buf, int len, char *magic)
+{
+  int ss;
+  char *pu;
+  grub_uint16_t us;
+  
+  DBG("%x-%x-%x-%x", buf[0], buf[1], buf[2], buf[3]);
+  if (grub_memcmp (buf, magic, 4))
+    return grub_error (GRUB_ERR_BAD_FS, "%s label not found", magic);
+
+  ss = u16at (buf, 6) - 1;
+  if (ss * (int) data->blocksize != len * GRUB_DISK_SECTOR_SIZE)
+    return grub_error (GRUB_ERR_BAD_FS, "size not match",
+        ss * (int) data->blocksize,
+        len * GRUB_DISK_SECTOR_SIZE);
+  pu = buf + u16at (buf, 4);
+  us = u16at (pu, 0);
+  buf -= 2;
+  while (ss > 0)
+    {
+      buf += data->blocksize;
+      pu += 2;
+      if (u16at (buf, 0) != us)
+ return grub_error (GRUB_ERR_BAD_FS, "fixup signature not match");
+      v16at (buf, 0) = v16at (pu, 0);
+      ss--;
+    }
+
+  return 0;
+}
+
+static grub_err_t read_mft (struct grub_ntfs_data *data, char *buf,
+     grub_uint32_t mftno);
+static grub_err_t read_attr (struct grub_ntfs_attr *at, char *dest,
+      grub_disk_addr_t ofs, grub_size_t len,
+      int cached,
+      void (*read_hook) (grub_disk_addr_t sector,
+ unsigned offset,
+ unsigned length,
+ void *closure),
+      void *closure);
+
+static grub_err_t read_data (struct grub_ntfs_attr *at, char *pa, char *dest,
+      grub_disk_addr_t ofs, grub_size_t len,
+      int cached,
+      void (*read_hook) (grub_disk_addr_t sector,
+ unsigned offset,
+ unsigned length,
+ void *closure),
+      void *closure);
+
+static void
+init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
+{
+  at->mft = mft;
+  at->flags = (mft == &mft->data->mmft) ? AF_MMFT : 0;
+  at->attr_nxt = mft->buf + u16at (mft->buf, 0x14);
+  at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
+}
+
+static void
+free_attr (struct grub_ntfs_attr *at)
+{
+  grub_free (at->emft_buf);
+  grub_free (at->edat_buf);
+  grub_free (at->sbuf);
+}
+
+static char *
+find_attr (struct grub_ntfs_attr *at, unsigned char attr)
+{
+  grub_off_t off_bytes1;
+  grub_off_t off_bytes2;
+  if (at->flags & AF_ALST)
+    {
+      DBG("!!!!!!\nin a attr list======");
+    retry:
+      while (at->attr_nxt < at->attr_end)
+ {
+   at->attr_cur = at->attr_nxt;
+   at->attr_nxt += u16at (at->attr_cur, 4);
+   if (((unsigned char) *at->attr_cur == attr) || (attr == 0))
+     {
+       char *new_pos;
+
+       if (at->flags & AF_MMFT)
+ {
+   DBG("in AF_MMFT......");
+   off_bytes1 = (grub_off_t)(v32at (at->attr_cur, 0x10)) << BLK_SHR;
+   off_bytes2 = (grub_off_t)(v32at (at->attr_cur, 0x14)) << BLK_SHR;
+   if ((bdrv_pread
+        (at->mft->data->bs, off_bytes1,
+ at->emft_buf, 512))
+       ||
+       (bdrv_pread
+        (at->mft->data->bs, off_bytes2,
+ at->emft_buf + 512, 512)))
+     return NULL;
+
+   if (fixup
+       (at->mft->data, at->emft_buf, at->mft->data->mft_size,
+        (char*)"FILE"))
+     return NULL;
+ }
+       else
+ {
+   DBG("read extend mft FR======");
+   if (read_mft (at->mft->data, at->emft_buf,
+ u32at (at->attr_cur, 0x10)))
+     return NULL;
+ }
+
+       new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)];
+       while ((unsigned char) *new_pos != 0xFF)
+ {
+   DBG("new pos in extend mft======");
+   if (((unsigned char) *new_pos ==
+        (unsigned char) *at->attr_cur)
+       && (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18)))
+     {
+       return new_pos;
+     }
+   new_pos += u16at (new_pos, 4);
+ }
+       grub_error (GRUB_ERR_BAD_FS,
+   "can\'t find 0x%X in attribute list",
+   (unsigned char) *at->attr_cur);
+       return NULL;
+     }
+ }
+      return NULL;
+    }
+
+
+  DBG("not in a attr list======");
+  at->attr_cur = at->attr_nxt;
+  while ((unsigned char) *at->attr_cur != 0xFF)
+    {
+      at->attr_nxt += u16at (at->attr_cur, 4);
+      if ((unsigned char) *at->attr_cur == AT_ATTRIBUTE_LIST)
+ at->attr_end = at->attr_cur;
+      if (((unsigned char) *at->attr_cur == attr) || (attr == 0))
+ {
+   DBG("found======");
+   return at->attr_cur;
+ }
+      at->attr_cur = at->attr_nxt;
+    }
+  
+  
+  if (at->attr_end)
+    {
+      DBG("searching in attr list======");
+      char *pa;
+
+      at->emft_buf = grub_malloc (at->mft->data->mft_size << BLK_SHR);
+      if (at->emft_buf == NULL)
+ return NULL;
+
+      pa = at->attr_end;
+      if (pa[8])
+ {
+          int n;
+
+          n = ((u32at (pa, 0x30) + GRUB_DISK_SECTOR_SIZE - 1)
+               & (~(GRUB_DISK_SECTOR_SIZE - 1)));
+   at->attr_cur = at->attr_end;
+   at->edat_buf = grub_malloc (n);
+   if (!at->edat_buf)
+     return NULL;
+   if (read_data (at, pa, at->edat_buf, 0, n, 0, 0, 0))
+     {
+       grub_error (GRUB_ERR_BAD_FS,
+   "fail to read non-resident attribute list");
+       return NULL;
+     }
+   at->attr_nxt = at->edat_buf;
+   at->attr_end = at->edat_buf + u32at (pa, 0x30);
+ }
+      else
+ {
+   at->attr_nxt = at->attr_end + u16at (pa, 0x14);
+   at->attr_end = at->attr_end + u32at (pa, 4);
+ }
+      at->flags |= AF_ALST;
+      while (at->attr_nxt < at->attr_end)
+ {
+   if (((unsigned char) *at->attr_nxt == attr) || (attr == 0))
+     break;
+   at->attr_nxt += u16at (at->attr_nxt, 4);
+ }
+      if (at->attr_nxt >= at->attr_end)
+ {
+   DBG("not found in list");
+   return NULL;
+ }
+      DBG("found in attr list======");
+      if ((at->flags & AF_MMFT) && (attr == AT_DATA))
+ {
+   DBG("AF_GPOS!!!!!!======");
+   at->flags |= AF_GPOS;
+   at->attr_cur = at->attr_nxt;
+   pa = at->attr_cur;
+   v32at (pa, 0x10) = at->mft->data->mft_start;
+   v32at (pa, 0x14) = at->mft->data->mft_start + 1;
+   pa = at->attr_nxt + u16at (pa, 4);
+   while (pa < at->attr_end)
+     {
+       if ((unsigned char) *pa != attr)
+ break;
+       if (read_attr
+   (at, pa + 0x10,
+    u32at (pa, 0x10) * (at->mft->data->mft_size << BLK_SHR),
+    at->mft->data->mft_size << BLK_SHR, 0, 0, 0))
+ return NULL;
+       pa += u16at (pa, 4);
+     }
+   at->attr_nxt = at->attr_cur;
+   at->flags &= ~AF_GPOS;
+ }
+      
+      DBG("goto retry======");
+      goto retry;
+    }
+
+  DBG("return NULL");
+  return NULL;
+}
+
+static char *
+locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
+      unsigned char attr)
+{
+  
+
+  char *pa;
+  
+  init_attr (at, mft);
+
+  DBG("\n!!!!!!\nlocating attr=0x%02x, at->flag=0x%02x============",
+      attr, at->flags);
+  if ((pa = find_attr (at, attr)) == NULL)
+    {
+      DBG("1=========not found");
+      return NULL;
+    }
+  if ((at->flags & AF_ALST) == 0)
+    {
+      DBG("2=======not a attr list, continue searching");
+      while (1)
+ {
+   if ((pa = find_attr (at, attr)) == NULL)
+     break;
+   if (at->flags & AF_ALST)
+     {
+       DBG("3==========in a attr list,found");
+       return pa;
+     }
+ }
+      DBG("4========start searching all over again");
+      grub_errno = GRUB_ERR_NONE;
+      free_attr (at);
+      init_attr (at, mft);
+      pa = find_attr (at, attr);
+    }
+  DBG("locate finish======\n\n");
+  return pa;
+}
+
+static char *
+read_run_data (char *run, int nn, grub_disk_addr_t * val, int sig)
+{
+  grub_disk_addr_t r, v;
+
+  r = 0;
+  v = 1;
+
+  while (nn--)
+    {
+      r += v * (*(unsigned char *) (run++));
+      v <<= 8;
+    }
+
+  if ((sig) && (r & (v >> 1)))
+    r -= v;
+
+  *val = r;
+  return run;
+}
+
+grub_err_t
+grub_ntfs_read_run_list (struct grub_ntfs_rlst * ctx)
+{
+  DBG("read run list");
+
+  int c1, c2;
+  grub_disk_addr_t val;
+  char *run;
+
+  run = ctx->cur_run;
+retry:
+  c1 = ((unsigned char) (*run) & 0xF);
+  c2 = ((unsigned char) (*run) >> 4);
+  if (!c1)
+    {
+      if ((ctx->attr) && (ctx->attr->flags & AF_ALST))
+ {
+   void (*save_hook) (grub_disk_addr_t sector,
+      unsigned offset,
+      unsigned length,
+      void *closure);
+   
+   //save_hook = ctx->comp.bs->read_hook;
+   //ctx->comp.bs->read_hook = 0;
+   run = find_attr (ctx->attr, (unsigned char) *ctx->attr->attr_cur);
+   //ctx->comp.bs->read_hook = save_hook;
+   if (run)
+     {
+       if (run[8] == 0)
+ return grub_error (GRUB_ERR_BAD_FS,
+    "$DATA should be non-resident");
+
+       run += u16at (run, 0x20);
+       ctx->curr_lcn = 0;
+       goto retry;
+     }
+ }
+      return grub_error (GRUB_ERR_BAD_FS, "run list overflown");
+    }
+  run = read_run_data (run + 1, c1, &val, 0); /* length of current VCN */
+  ctx->curr_vcn = ctx->next_vcn;
+  ctx->next_vcn += val;
+  run = read_run_data (run, c2, &val, 1); /* offset to previous LCN */
+  ctx->curr_lcn += val;
+  if (val == 0)
+    ctx->flags |= RF_BLNK;
+  else
+    ctx->flags &= ~RF_BLNK;
+  ctx->cur_run = run;
+  return 0;
+}
+
+static grub_disk_addr_t
+grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block)
+{
+  struct grub_ntfs_rlst *ctx;
+
+  ctx = (struct grub_ntfs_rlst *) node;
+  if (block >= ctx->next_vcn)
+    {
+      if (grub_ntfs_read_run_list (ctx))
+ return -1;
+      return ctx->curr_lcn;
+    }
+  else
+    return (ctx->flags & RF_BLNK) ? 0 : (block -
+  ctx->curr_vcn + ctx->curr_lcn);
+}
+
+static grub_err_t
+read_data (struct grub_ntfs_attr *at, char *pa, char *dest,
+    grub_disk_addr_t ofs, grub_size_t len, int cached,
+    void (*read_hook) (grub_disk_addr_t sector,
+       unsigned offset,
+       unsigned length,
+       void *closure),
+    void *closure)
+{
+  grub_disk_addr_t vcn;
+  struct grub_ntfs_rlst cc, *ctx;
+
+  if (len == 0)
+    return 0;
+
+  grub_memset (&cc, 0, sizeof (cc));
+  ctx = &cc;
+  ctx->attr = at;
+  ctx->comp.spc = at->mft->data->spc;
+  ctx->comp.bs = at->mft->data->bs;
+
+  if (pa[8] == 0)
+    {
+      if (ofs + len > u32at (pa, 0x10))
+ return grub_error (GRUB_ERR_BAD_FS, "read out of range");
+      grub_memcpy (dest, pa + u32at (pa, 0x14) + ofs, len);
+      return 0;
+    }
+
+  if (u16at (pa, 0xC) & FLAG_COMPRESSED)
+    ctx->flags |= RF_COMP;
+  else
+    ctx->flags &= ~RF_COMP;
+  ctx->cur_run = pa + u16at (pa, 0x20);
+
+  if (ctx->flags & RF_COMP)
+    {
+      if (!cached)
+ return grub_error (GRUB_ERR_BAD_FS, "attribute can\'t be compressed");
+
+      if (at->sbuf)
+ {
+   if ((ofs & (~(COM_LEN - 1))) == at->save_pos)
+     {
+       grub_disk_addr_t n;
+
+       n = COM_LEN - (ofs - at->save_pos);
+       if (n > len)
+ n = len;
+
+       grub_memcpy (dest, at->sbuf + ofs - at->save_pos, n);
+       if (n == len)
+ return 0;
+
+       dest += n;
+       len -= n;
+       ofs += n;
+     }
+ }
+      else
+ {
+   at->sbuf = grub_malloc (COM_LEN);
+   if (at->sbuf == NULL)
+     return grub_errno;
+   at->save_pos = 1;
+ }
+
+      vcn = ctx->target_vcn = (ofs >> COM_LOG_LEN) * (COM_SEC / ctx->comp.spc);
+      ctx->target_vcn &= ~0xF;
+    }
+  else
+    vcn = ctx->target_vcn = grub_divmod64 (ofs >> BLK_SHR, ctx->comp.spc, 0);
+
+  ctx->next_vcn = u32at (pa, 0x10);
+  ctx->curr_lcn = 0;
+  while (ctx->next_vcn <= ctx->target_vcn)
+    {
+      if (grub_ntfs_read_run_list (ctx))
+ return grub_errno;
+    }
+
+  if (at->flags & AF_GPOS)
+    {
+      grub_disk_addr_t st0, st1;
+      grub_uint32_t m;
+
+      grub_divmod64 (ofs >> BLK_SHR, ctx->comp.spc, &m);
+
+      st0 =
+ (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc + m;
+      st1 = st0 + 1;
+      if (st1 ==
+   (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc)
+ {
+   if (grub_ntfs_read_run_list (ctx))
+     return grub_errno;
+   st1 = ctx->curr_lcn * ctx->comp.spc;
+ }
+      v32at (dest, 0) = st0;
+      v32at (dest, 4) = st1;
+      return 0;
+    }
+
+  if (!(ctx->flags & RF_COMP))
+    {
+      unsigned int pow;
+
+      if (!grub_fshelp_log2blksize (ctx->comp.spc, &pow))
+ grub_fshelp_read_file (ctx->comp.bs, (grub_fshelp_node_t) ctx,
+        read_hook, closure, ofs, len, dest,
+        grub_ntfs_read_block, ofs + len, pow);
+      return grub_errno;
+    }
+
+  return (grub_ntfscomp_func) ? grub_ntfscomp_func (at, dest, ofs, len, ctx,
+     vcn) :
+    grub_error (GRUB_ERR_BAD_FS, "ntfscomp module not loaded");
+}
+
+static grub_err_t
+read_attr (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs,
+    grub_size_t len, int cached,
+    void (*read_hook) (grub_disk_addr_t sector,
+       unsigned offset,
+       unsigned length,
+       void *closure),
+    void *closure)
+{
+  DBG("read attr");
+  
+  char *save_cur;
+  unsigned char attr;
+  char *pp;
+  grub_err_t ret;
+
+  save_cur = at->attr_cur;
+  at->attr_nxt = at->attr_cur;
+  attr = (unsigned char) *at->attr_nxt;
+  if (at->flags & AF_ALST)
+    {
+      char *pa;
+      grub_disk_addr_t vcn;
+
+      vcn = grub_divmod64 (ofs, at->mft->data->spc << BLK_SHR, 0);
+      pa = at->attr_nxt + u16at (at->attr_nxt, 4);
+      while (pa < at->attr_end)
+ {
+   if ((unsigned char) *pa != attr)
+     break;
+   if (u32at (pa, 8) > vcn)
+     break;
+   at->attr_nxt = pa;
+   pa += u16at (pa, 4);
+ }
+    }
+  pp = find_attr (at, attr);
+  if (pp)
+    ret = read_data (at, pp, dest, ofs, len, cached, read_hook, closure);
+  else
+    ret =
+      (grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS,
+       "attribute not found");
+  at->attr_cur = save_cur;
+  return ret;
+}
+
+static grub_err_t
+read_mft (struct grub_ntfs_data *data, char *buf, grub_uint32_t mftno)
+{
+  if (read_attr
+      (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size) << BLK_SHR,
+       data->mft_size << BLK_SHR, 0, 0, 0))
+    return grub_error (GRUB_ERR_BAD_FS, "Read MFT 0x%X fails", mftno);
+  return fixup (data, buf, data->mft_size, (char*)"FILE");
+}
+
+static grub_err_t
+init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno)
+{
+  DBG("init file");
+  
+  unsigned short flag;
+
+  mft->inode_read = 1;
+
+  mft->buf = grub_malloc (mft->data->mft_size << BLK_SHR);
+  if (mft->buf == NULL)
+    return grub_errno;
+
+  if (read_mft (mft->data, mft->buf, mftno))
+    return grub_errno;
+
+  flag = u16at (mft->buf, 0x16);
+  if ((flag & 1) == 0)
+    return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%X is not in use", mftno);
+
+  if ((flag & 2) == 0)
+    {
+      char *pa;
+
+      pa = locate_attr (&mft->attr, mft, AT_DATA);
+      if (pa == NULL)
+ return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%X", mftno);
+
+      if (!pa[8])
+ mft->size = u32at (pa, 0x10);
+      else
+ mft->size = u64at (pa, 0x30);
+
+      if ((mft->attr.flags & AF_ALST) == 0)
+ mft->attr.attr_end = 0; /*  Don't jump to attribute list */
+    }
+  else
+    init_attr (&mft->attr, mft);
+
+  return 0;
+}
+
+static void
+free_file (struct grub_ntfs_file *mft)
+{
+  free_attr (&mft->attr);
+  grub_free (mft->buf);
+}
+
+static int
+list_file (struct grub_ntfs_file *diro, char *pos,
+    int (*hook) (const char *filename,
+ enum grub_fshelp_filetype filetype,
+ grub_fshelp_node_t node,
+ void *closure),
+    void *closure)
+{
+  char *np;
+  int ns;
+
+  while (1)
+    {
+      char *ustr, namespace;
+      char* gbstr;
+
+      if (pos[0xC] & 2) /* end signature */
+ break;
+
+      np = pos + 0x50;
+      ns = (unsigned char) *(np++);
+      namespace = *(np++);
+
+      /*
+       *  Ignore files in DOS namespace, as they will reappear as Win32
+       *  names.
+       */
+      if ((ns) && (namespace != 2))
+ {
+   enum grub_fshelp_filetype type;
+   struct grub_ntfs_file *fdiro;
+
+   if (u16at (pos, 4))
+     {
+       grub_error (GRUB_ERR_BAD_FS, "64-bit MFT number");
+       return 0;
+     }
+
+   type =
+     (u32at (pos, 0x48) & ATTR_DIRECTORY) ? GRUB_FSHELP_DIR :
+     GRUB_FSHELP_REG;
+
+   fdiro = grub_zalloc (sizeof (struct grub_ntfs_file));
+   if (!fdiro)
+     return 0;
+
+   fdiro->data = "">
+   fdiro->ino = u32at (pos, 0);
+
+   ustr = grub_malloc (ns * 4 + 1);
+   gbstr = grub_malloc(ns * 2 + 1);
+     if (ustr == NULL || gbstr == NULL)
+     return 0;
+   *grub_utf16_to_utf8 ((grub_uint8_t *) ustr, (grub_uint16_t *) np,
+        ns) = '\0';
+   u2g(ustr, strlen(ustr), gbstr, ns * 2 + 1);
+   DBG("gbstr=%s", gbstr);
+          if (namespace)
+            type |= GRUB_FSHELP_CASE_INSENSITIVE;
+
+   if (hook (gbstr, type, fdiro, closure))
+     {
+       grub_free (ustr);
+       grub_free (gbstr);
+       return 1;
+     }
+   grub_free(gbstr);
+   grub_free (ustr);
+ }
+      pos += u16at (pos, 8);
+    }
+  return 0;
+}
+
+static int
+grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+        int (*hook) (const char *filename,
+     enum grub_fshelp_filetype filetype,
+     grub_fshelp_node_t node,
+     void *closure),
+        void *closure)
+{
+  unsigned char *bitmap;
+  struct grub_ntfs_attr attr, *at;
+  char *cur_pos, *indx, *bmp;
+  int ret = 0;
+  grub_size_t bitmap_len;
+  struct grub_ntfs_file *mft;
+
+  mft = (struct grub_ntfs_file *) dir;
+
+  if (!mft->inode_read)
+    {
+      if (init_file (mft, mft->ino))
+ return 0;
+    }
+
+  indx = NULL;
+  bmp = NULL;
+
+  at = &attr;
+  init_attr (at, mft);
+  while (1)
+    {
+      if ((cur_pos = find_attr (at, AT_INDEX_ROOT)) == NULL)
+ {
+   grub_error (GRUB_ERR_BAD_FS, "no $INDEX_ROOT");
+   goto done;
+ }
+
+      /* Resident, Namelen=4, Offset=0x18, Flags=0x00, Name="$I30" */
+      if ((u32at (cur_pos, 8) != 0x180400) ||
+   (u32at (cur_pos, 0x18) != 0x490024) ||
+   (u32at (cur_pos, 0x1C) != 0x300033))
+ continue;
+      cur_pos += u16at (cur_pos, 0x14);
+      if (*cur_pos != 0x30) /* Not filename index */
+ continue;
+      break;
+    }
+
+  cur_pos += 0x10; /* Skip index root */
+  ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, closure);
+  if (ret)
+    goto done;
+    
+
+  bitmap = NULL;
+  bitmap_len = 0;
+  free_attr (at);
+  init_attr (at, mft);
+  while ((cur_pos = find_attr (at, AT_BITMAP)) != NULL)
+    {
+      int ofs;
+
+      ofs = (unsigned char) cur_pos[0xA];
+      /* Namelen=4, Name="$I30" */
+      if ((cur_pos[9] == 4) &&
+   (u32at (cur_pos, ofs) == 0x490024) &&
+   (u32at (cur_pos, ofs + 4) == 0x300033))
+ {
+          int is_resident = (cur_pos[8] == 0);
+
+          bitmap_len = ((is_resident) ? u32at (cur_pos, 0x10) :
+                        u32at (cur_pos, 0x28));
+
+          bmp = grub_malloc (bitmap_len);
+          if (bmp == NULL)
+            goto done;
+
+   if (is_resident)
+     {
+              grub_memcpy (bmp, (char *) (cur_pos + u16at (cur_pos, 0x14)),
+                           bitmap_len);
+     }
+          else
+            {
+              if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0, 0))
+                {
+                  grub_error (GRUB_ERR_BAD_FS,
+                              "fails to read non-resident $BITMAP");
+                  goto done;
+                }
+              bitmap_len = u32at (cur_pos, 0x30);
+            }
+
+          bitmap = (unsigned char *) bmp;
+   break;
+ }
+    }
+
+  free_attr (at);
+  cur_pos = locate_attr (at, mft, AT_INDEX_ALLOCATION);
+  while (cur_pos != NULL)
+    {
+      /* Non-resident, Namelen=4, Offset=0x40, Flags=0, Name="$I30" */
+      if ((u32at (cur_pos, 8) == 0x400401) &&
+   (u32at (cur_pos, 0x40) == 0x490024) &&
+   (u32at (cur_pos, 0x44) == 0x300033))
+ break;
+      cur_pos = find_attr (at, AT_INDEX_ALLOCATION);
+    }
+
+  if ((!cur_pos) && (bitmap))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "$BITMAP without $INDEX_ALLOCATION");
+      goto done;
+    }
+
+  if (bitmap)
+    {
+      grub_disk_addr_t v, i;
+
+      indx = grub_malloc (mft->data->idx_size << BLK_SHR);
+      if (indx == NULL)
+ goto done;
+
+      v = 1;
+      for (i = 0; i < (grub_disk_addr_t)bitmap_len * 8; i++)
+ {
+   if (*bitmap & v)
+     {
+       if ((read_attr
+    (at, indx, i * (mft->data->idx_size << BLK_SHR),
+     (mft->data->idx_size << BLK_SHR), 0, 0, 0))
+   || (fixup (mft->data, indx, mft->data->idx_size, (char*)"INDX")))
+ goto done;
+       ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook,
+        closure);
+       if (ret)
+ goto done;
+     }
+   v <<= 1;
+   if (v >= 0x100)
+     {
+       v = 1;
+       bitmap++;
+     }
+ }
+    }
+
+done:
+  free_attr (at);
+  grub_free (indx);
+  grub_free (bmp);
+
+  return ret;
+}
+
+
+struct grub_ntfs_data *
+grub_ntfs_mount (BlockDriverState* bs, grub_uint32_t part_off_sector)
+{
+  struct grub_ntfs_bpb bpb;
+  struct grub_ntfs_data *data = "">
+  grub_off_t off_bytes = (grub_off_t)part_off_sector << BLK_SHR; 
+  
+  if (!bs)
+    goto fail;
+
+  data = "" grub_ntfs_data *) grub_zalloc (sizeof (*data));
+  if (!data)
+    goto fail;
+
+  data->bs = bs;
+
+  /* Read the BPB.  */
+  if (bdrv_pread (bs, off_bytes, &bpb, sizeof (bpb)) != sizeof(bpb))
+    {
+      DBG("read bpb err!");
+      goto fail;
+    }
+  if (grub_memcmp ((char *) &bpb.oem_name, "NTFS", 4))
+    {
+      DBG("bpb.oem_name=%s, not ntfs", bpb.oem_name);
+      goto fail;
+    }
+  data->blocksize = grub_le_to_cpu16 (bpb.bytes_per_sector);
+  data->spc = bpb.sectors_per_cluster * (data->blocksize >> BLK_SHR);
+
+  if (bpb.clusters_per_mft > 0)
+    data->mft_size = data->spc * bpb.clusters_per_mft;
+  else
+    data->mft_size = 1 << (-bpb.clusters_per_mft - BLK_SHR);
+
+  if (bpb.clusters_per_index > 0)
+    data->idx_size = data->spc * bpb.clusters_per_index;
+  else
+    data->idx_size = 1 << (-bpb.clusters_per_index - BLK_SHR);
+
+  data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) * data->spc;
+
+  if ((data->mft_size > MAX_MFT) || (data->idx_size > MAX_IDX))
+    goto fail;
+
+  data->mmft.data = "">
+  data->cmft.data = "">
+
+  data->mmft.buf = grub_malloc (data->mft_size << BLK_SHR);
+  if (!data->mmft.buf)
+    goto fail;
+
+  s_bpb_bytes_per_sector = (bpb.bytes_per_sector);
+  s_part_off_sector = part_off_sector;
+  DBG("bpb.bytes_per_sector=blocksize=%u\n"
+      "bpb.sector_per_cluster=%u\n"
+      "data->blocksize=%u\n"
+      "data->spc=%u\n"
+      "bpb.clusters_per_mft=%d\n"
+      "data->mft_size=%u\n"
+      "bpb.total_sectors=%zd\n"
+      "bpb.mft_lcn=%zd\n"
+      "data->mft_start=%u\n",
+      (bpb.bytes_per_sector), (bpb.sectors_per_cluster),
+      (data->blocksize), (data->spc),
+      (bpb.clusters_per_mft), (data->mft_size),
+      (bpb.num_total_sectors),
+      (grub_le_to_cpu64(bpb.mft_lcn)), (data->mft_start));
+  
+  off_bytes = (grub_off_t)data->mft_start << BLK_SHR;
+  grub_uint32_t len = data->mft_size << BLK_SHR;
+  if (bdrv_pread_from_lcn_of_volum(bs, off_bytes,
+  data->mmft.buf, len) != len)
+    {
+      DBG("read mmft error!");
+      goto fail;
+    }
+  data->uuid = grub_le_to_cpu64 (bpb.num_serial);
+
+  if (fixup (data, data->mmft.buf, data->mft_size, (char*)"FILE"))
+    goto fail;
+
+  if (!locate_attr (&data->mmft.attr, &data->mmft, AT_DATA))
+    {
+      DBG("locate_attr AT_DATA in mmft failed! ");
+      goto fail;
+    }
+  if (init_file (&data->cmft, FILE_ROOT))
+    {
+      DBG("init_file FILE_ROOT failed!");
+      goto fail;
+    }
+  return data;
+
+fail:
+  grub_error (GRUB_ERR_BAD_FS, "not an ntfs filesystem");
+
+  if (data)
+    {
+      free_file (&data->mmft);
+      free_file (&data->cmft);
+      grub_free (data);
+    }
+  return 0;
+}
+
+struct grub_ntfs_dir_closure
+{
+  int (*hook) (const char *filename,
+        const struct grub_dirhook_info *info,
+        void *closure);
+  void *closure;
+  struct grub_ntfs_file file;
+};
+
+static int
+iterate (const char *filename,
+  enum grub_fshelp_filetype filetype,
+  grub_fshelp_node_t node,
+  void *closure)
+{
+  struct grub_ntfs_dir_closure *c = closure;
+  struct grub_dirhook_info info;
+  grub_memset (&info, 0, sizeof (info));
+  info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+  c->file.data = "">
+  c->file.ino = node->ino;
+  grub_free (node);
+  
+  
+  if(init_file(&c->file, c->file.ino))
+    {
+      errx(1, "iterate(): init_file error!\n");
+    }
+  else
+    {
+      DBG("......current file mft read successfully!\n");
+    }
+  char *pa = locate_attr(&c->file.attr,
+  &c->file, AT_STANDARD_INFORMATION);
+  if(NULL == pa)
+    {
+      errx(2, "no $STANDARD_INFORMATION in MFT 0x%x\n", c->file.ino);
+    }
+  grub_uint64_t date= 0;
+  if(read_attr(&c->file.attr, (char*)&date, 0, 8, 1, NULL, NULL))
+    {
+      errx(3, "read date error\n");
+    }
+  else
+    {
+
+      info.time_ntfs = date;
+      DBG("......date: %zu\n", date);
+    }
+  DBG("......size of \'%s\': %zu\n", filename, (c->file.size));
+  info.filesize_ntfs = c->file.size;
+  free_file(&c->file);
+  return c->hook (filename, &info, c->closure);
+}
+
+
+#include "fs-time.h"
+static  int find_then_ls_hook(const char *filename,
+    const struct grub_dirhook_info *info, void *closure)
+{
+  struct ls_ctrl* ctrl = (struct ls_ctrl*)closure;
+  DBG("detail=%d", ctrl->detail);
+  if('$' == *filename)
+    goto done;
+
+  printf("%s", filename);
+  if(!ctrl->detail)
+    {
+      printf("\n");
+      goto done;
+    }
+  else
+    {
+      printf("\t");
+    }
+  
+  char buffer[50]={};
+  struct tm tm0;  
+  struct tm* ptm= ntfs_utc2local(info->time_ntfs, &tm0);
+  if(NULL == ptm) errx(1, "ntfs_utc2local fail\n");
+           
+  printf("%zu\t", info->filesize_ntfs);
+  printf("%s\t", (info->dir ? "dir" : "file"));
+  strftime(buffer, 50, "%Y-%m-%d\t%H:%M:%S", ptm);
+  printf("%s", buffer);
+  //printf("%d-%d-%d\t", ptm->tm_year, ptm->tm_mon, ptm->tm_mday);
+  //printf("%d:%d:%d\t", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
+  printf("\n");
+
+ done:
+  return 0;  // 最终返回给iterate
+}
+
+
+
+grub_err_t
+grub_ntfs_ls (grub_file_t file, const char *path,
+        int (*hook) (const char *filename,
+     const struct grub_dirhook_info *info,
+     void *closure),
+        void *closure)
+{
+  struct grub_ntfs_data *data = "">
+  struct grub_fshelp_node *fdiro = 0;
+  struct grub_ntfs_dir_closure c = {0};
+
+  data = "" (file->bs, file->part_off_sector);
+  if (!data)
+    {
+      DBG("mount failed!");
+      goto fail;
+    }
+  grub_fshelp_find_file (path, &data->cmft, &fdiro, grub_ntfs_iterate_dir, 0,
+  0, GRUB_FSHELP_DIR);
+
+  
+  if (grub_errno)
+    goto fail;
+
+  c.hook = (hook ? hook : find_then_ls_hook);
+  c.closure = closure;
+  grub_ntfs_iterate_dir (fdiro, iterate, &c);
+
+fail:
+  if ((fdiro) && (fdiro != &data->cmft))
+    {
+      free_file (fdiro);
+      grub_free (fdiro);
+    }
+  if (data)
+    {
+      free_file (&data->mmft);
+      free_file (&data->cmft);
+      grub_free (data);
+    }
+
+
+  return grub_errno;
+}
+
+grub_err_t
+grub_ntfs_open (grub_file_t file, const char *name)
+{
+  struct grub_ntfs_data *data = "">
+  struct grub_fshelp_node *mft = 0;
+
+
+  data = "" (file->bs, file->part_off_sector);
+  if (!data)
+    {
+      DBG("mount failed!");
+      goto fail;
+    }
+  grub_fshelp_find_file (name, &data->cmft, &mft, grub_ntfs_iterate_dir, 0,
+  0, GRUB_FSHELP_REG);
+
+  if (grub_errno)
+    goto fail;
+
+  if (mft != &data->cmft)
+    {
+      free_file (&data->cmft);
+      grub_memcpy (&data->cmft, mft, sizeof (*mft));
+      grub_free (mft);
+      if (!data->cmft.inode_read)
+ {
+   if (init_file (&data->cmft, data->cmft.ino))
+     goto fail;
+ }
+    }
+
+  file->size = data->cmft.size;
+  file->data = "">
+  file->offset = 0;
+
+  return 0;
+
+fail:
+  if (data)
+    {
+      free_file (&data->mmft);
+      free_file (&data->cmft);
+      grub_free (data);
+    }
+
+
+  return grub_errno;
+}
+
+grub_ssize_t
+grub_ntfs_read (grub_file_t file, grub_off_t offset, grub_size_t len, char *buf)
+{
+  struct grub_ntfs_file *mft;
+
+  mft = &((struct grub_ntfs_data *) file->data)->cmft;
+  if (file->read_hook)
+    mft->attr.save_pos = 1;
+  
+  read_attr (&mft->attr, buf, offset, len, 1,
+      file->read_hook, file->closure);
+  
+  return (grub_errno) ? 0 : len;
+}
+
+grub_err_t
+grub_ntfs_close (grub_file_t file)
+{
+  struct grub_ntfs_data *data;
+
+  data = "">
+
+  if (data)
+    {
+      free_file (&data->mmft);
+      free_file (&data->cmft);
+      grub_free (data);
+    }
+
+
+  return grub_errno;
+}
+
+
+
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/ntfs.h xen-4.1.2-b/tools/ioemu-qemu-xen/ntfs.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/ntfs.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/ntfs.h 2012-12-28 16:02:41.014936701 +0800
@@ -0,0 +1,227 @@
+/* ntfs.h - header for the NTFS filesystem */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_NTFS_H
+#define GRUB_NTFS_H 1
+
+
+#include "block_int.h"
+#include "fs-types.h"
+#include "grub_err.h"
+#include "fs-comm.h"
+
+#define FILE_MFT      0
+#define FILE_MFTMIRR  1
+#define FILE_LOGFILE  2
+#define FILE_VOLUME   3
+#define FILE_ATTRDEF  4
+#define FILE_ROOT     5
+#define FILE_BITMAP   6
+#define FILE_BOOT     7
+#define FILE_BADCLUS  8
+#define FILE_QUOTA    9
+#define FILE_UPCASE  10
+
+#define AT_STANDARD_INFORMATION 0x10
+#define AT_ATTRIBUTE_LIST 0x20
+#define AT_FILENAME 0x30
+#define AT_OBJECT_ID 0x40
+#define AT_SECURITY_DESCRIPTOR 0x50
+#define AT_VOLUME_NAME 0x60
+#define AT_VOLUME_INFORMATION 0x70
+#define AT_DATA 0x80
+#define AT_INDEX_ROOT 0x90
+#define AT_INDEX_ALLOCATION 0xA0
+#define AT_BITMAP 0xB0
+#define AT_SYMLINK 0xC0
+#define AT_EA_INFORMATION 0xD0
+#define AT_EA 0xE0
+
+#define ATTR_READ_ONLY 0x1
+#define ATTR_HIDDEN 0x2
+#define ATTR_SYSTEM 0x4
+#define ATTR_ARCHIVE 0x20
+#define ATTR_DEVICE 0x40
+#define ATTR_NORMAL 0x80
+#define ATTR_TEMPORARY 0x100
+#define ATTR_SPARSE 0x200
+#define ATTR_REPARSE 0x400
+#define ATTR_COMPRESSED 0x800
+#define ATTR_OFFLINE 0x1000
+#define ATTR_NOT_INDEXED 0x2000
+#define ATTR_ENCRYPTED 0x4000
+#define ATTR_DIRECTORY 0x10000000
+#define ATTR_INDEX_VIEW 0x20000000
+
+#define FLAG_COMPRESSED 1
+#define FLAG_ENCRYPTED 0x4000
+#define FLAG_SPARSE 0x8000
+
+
+#define GRUB_DISK_SECTOR_BITS   9
+#define BLK_SHR GRUB_DISK_SECTOR_BITS
+
+#define MAX_MFT (1024 >> BLK_SHR)
+#define MAX_IDX (16384 >> BLK_SHR)
+
+#define COM_LEN 4096
+#define COM_LOG_LEN 12
+#define COM_SEC (COM_LEN >> BLK_SHR)
+
+#define AF_ALST 1
+#define AF_MMFT 2
+#define AF_GPOS 4
+
+#define RF_COMP 1
+#define RF_CBLK 2
+#define RF_BLNK 4
+
+#define valueat(buf,ofs,type) *((type*)(((char*)buf)+ofs))
+
+#define u16at(buf,ofs) grub_le_to_cpu16(valueat(buf,ofs,grub_uint16_t))
+#define u32at(buf,ofs) grub_le_to_cpu32(valueat(buf,ofs,grub_uint32_t))
+#define u64at(buf,ofs) grub_le_to_cpu64(valueat(buf,ofs,grub_uint64_t))
+
+#define v16at(buf,ofs) valueat(buf,ofs,grub_uint16_t)
+#define v32at(buf,ofs) valueat(buf,ofs,grub_uint32_t)
+#define v64at(buf,ofs) valueat(buf,ofs,grub_uint64_t)
+
+struct grub_ntfs_bpb
+{
+  grub_uint8_t jmp_boot[3];
+  grub_uint8_t oem_name[8];
+  grub_uint16_t bytes_per_sector;
+  grub_uint8_t sectors_per_cluster;
+  grub_uint8_t reserved_1[7];
+  grub_uint8_t media;
+  grub_uint16_t reserved_2;
+  grub_uint16_t sectors_per_track;
+  grub_uint16_t num_heads;
+  grub_uint32_t num_hidden_sectors;
+  grub_uint32_t reserved_3[2];
+  grub_uint64_t num_total_sectors;
+  grub_uint64_t mft_lcn;
+  grub_uint64_t mft_mirr_lcn;
+  grub_int8_t clusters_per_mft;
+  grub_int8_t reserved_4[3];
+  grub_int8_t clusters_per_index;
+  grub_int8_t reserved_5[3];
+  grub_uint64_t num_serial;
+  grub_uint32_t checksum;
+} __attribute__ ((packed));
+
+#define grub_ntfs_file grub_fshelp_node
+
+struct grub_ntfs_attr
+{
+  int flags;
+  char *emft_buf, *edat_buf;
+  char *attr_cur, *attr_nxt, *attr_end;
+  grub_uint32_t save_pos;
+  char *sbuf;
+  struct grub_ntfs_file *mft;
+};
+
+struct grub_fshelp_node
+{
+  struct grub_ntfs_data *data;
+  char *buf;
+  grub_uint64_t size;
+  grub_uint32_t ino;
+  int inode_read;
+  struct grub_ntfs_attr attr;
+};
+
+struct grub_ntfs_data
+{
+  struct grub_ntfs_file cmft;
+  struct grub_ntfs_file mmft;
+  BlockDriverState* bs;
+  grub_uint32_t mft_size;
+  grub_uint32_t idx_size;
+  grub_uint32_t spc;
+  grub_uint32_t blocksize;
+  grub_uint32_t mft_start;
+  grub_uint64_t uuid;
+};
+
+struct grub_ntfs_comp
+{
+  BlockDriverState* bs;
+  int comp_head, comp_tail;
+  grub_uint32_t comp_table[16][2];
+  grub_uint32_t cbuf_ofs, cbuf_vcn, spc;
+  char *cbuf;
+};
+
+struct grub_ntfs_rlst
+{
+  int flags;
+  grub_disk_addr_t target_vcn, curr_vcn, next_vcn, curr_lcn;
+  char *cur_run;
+  struct grub_ntfs_attr *attr;
+  struct grub_ntfs_comp comp;
+};
+
+
+
+
+
+
+
+typedef grub_err_t (*ntfscomp_func_t) (struct grub_ntfs_attr * at, char *dest,
+        grub_uint32_t ofs, grub_uint32_t len,
+        struct grub_ntfs_rlst * ctx,
+        grub_uint32_t vcn);
+
+extern ntfscomp_func_t grub_ntfscomp_func;
+
+grub_err_t grub_ntfs_read_run_list (struct grub_ntfs_rlst *ctx);
+
+
+
+
+int bdrv_pread_from_lcn_of_volum(BlockDriverState *bs, int64_t offset,
+  void *buf1, int count1);
+
+struct grub_ntfs_data *
+grub_ntfs_mount (BlockDriverState* bs, grub_uint32_t part_off_sector);
+
+
+grub_err_t
+grub_ntfs_ls (grub_file_t file, const char *path,
+        int (*hook) (const char *filename,
+     const struct grub_dirhook_info *info,
+     void *closure),
+       void *closure);
+
+grub_err_t
+grub_ntfs_open (grub_file_t file, const char *name);
+
+
+grub_ssize_t
+grub_ntfs_read (grub_file_t file, grub_off_t offset,
+ grub_size_t len, char *buf);
+
+
+grub_err_t
+grub_ntfs_close (grub_file_t file);
+
+
+#endif /* ! GRUB_NTFS_H */
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/partition.c xen-4.1.2-b/tools/ioemu-qemu-xen/partition.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/partition.c 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/partition.c 2012-12-28 16:02:41.014936701 +0800
@@ -0,0 +1,240 @@
+#include "partition.h"
+#include <err.h>
+
+static int is_full_zero(void *p, uint bytes)
+{
+  int i = 0;
+  uint8_t *p1 = (uint8_t*)p;
+  while(i < bytes)
+  {
+    if(*p1 != 0)
+    {
+      return 0;
+    }else
+    {
+      i++;
+      p1++;
+    }
+  }
+  //printf("..........full zero......\n");
+  return 1;
+}
+
+static void read_partition(uint8_t *p, struct partition_record *r)
+{
+    r->bootable = p[0];
+    r->start_head = p[1];
+    r->start_cylinder = p[3] | ((p[2] << 2) & 0x0300);
+    r->start_sector = p[2] & 0x3f;
+    r->system = p[4];
+    r->end_head = p[5];
+    r->end_cylinder = p[7] | ((p[6] << 2) & 0x300);
+    r->end_sector = p[6] & 0x3f;
+    r->start_sector_abs = p[8] | p[9] << 8 | p[10] << 16 | p[11] << 24;
+    r->nb_sectors_abs = p[12] | p[13] << 8 | p[14] << 16 | p[15] << 24;
+}
+
+
+
+char* judge_fs(ls_partition_t* pt)
+{
+  if(pt->part.system==0x0b || pt->part.system==0x01)
+    {
+      pt->fs_type = FS_FAT;
+      return (char*)"FAT32";
+    }
+  else if(pt->part.system==0x07)
+    {
+      pt->fs_type = FS_NTFS;
+      return (char*)"NTFS";
+    }
+  else
+    {
+      pt->fs_type = FS_UNKNOWN;
+      return  (char*)"UNKNOWN";
+    }
+}
+
+int enum_partition(BlockDriverState *bs, ls_partition_t* parts)
+{
+    struct partition_record mbr[4];
+    uint8_t data[512];
+    int i;
+    int ext_partnum = 4;
+    struct partition_record ext[10];
+    uint8_t data1[512];
+    int j = 0;
+
+    if (bdrv_read(bs, 0, data, 1))
+        errx(EINVAL, "error while reading");
+
+    if (data[510] != 0x55 || data[511] != 0xaa) 
+    {
+        errno = -EINVAL;
+        return -1;
+    }
+    
+    int k = 0;
+    for (i = 0; i < 4; i++) 
+    {
+        read_partition(&data[446 + 16 * i], &mbr[i]);
+
+        if (!mbr[i].nb_sectors_abs)
+            continue;
+ //printf("the %d partition:boot=0x%x, start=%u, system=0x%x, total=%u\t", 
+ //       i+1, mbr[i].bootable, mbr[i].start_sector_abs, mbr[i].system, mbr[i].nb_sectors_abs);
+ parts[k].part = mbr[i];
+ parts[k].id = i+1;
+ k++;
+        if (mbr[i].system == 0xF || mbr[i].system == 0x5) 
+ {
+     //printf("is a extend partition......\n");
+     if (bdrv_read(bs, mbr[i].start_sector_abs, data1, 1))
+                errx(EINVAL, "error while reading");
+     ///////////////////////////
+     //dump ebr
+     ///////////////////////////
+     uint32_t ext_start_sector = mbr[i].start_sector_abs;
+     struct partition_record ext_next = {0};
+            while (1) 
+     {
+         read_partition(&data1[446 + 16 * 0], &ext[j]);
+ //printf("the %dth partition:boot=0x%x, start=%u, system=0x%x, total=%u\t",
+ //       ext_partnum+j+1, ext[j].bootable, ext[j].start_sector_abs+ext_start_sector, 
+ //       ext[j].system, ext[j].nb_sectors_abs);
+
+
+ if(0 != ext[j].nb_sectors_abs) 
+ {
+   ext[j].start_sector_abs += ext_start_sector;
+   if(j > 0)
+     ext[j].start_sector_abs += ext_next.start_sector_abs;
+   parts[k].part = ext[j];
+   parts[k].id = ext_partnum + j +1;
+   k++;
+   j++;
+         }
+ else
+ {
+   printf("nb_sectors_abs=0>>>>>>>>>>>>\n");
+ }
+ //////////////////////
+ if(ext[j-1].system == 0xF )
+   {
+     printf("...............again extend.............\n");
+     ext_start_sector = ext[j-1].start_sector_abs + ext_start_sector;
+     if (bdrv_read(bs, ext_start_sector, data1, 1))
+       errx(EINVAL, "error while reading");
+     continue;
+   }
+ else
+   {
+     ;//printf("is a logical part\n");
+   }
+ /////////////////////
+ read_partition(&data1[446 + 16 * 1], &ext_next);
+ if (is_full_zero(&ext_next, sizeof(ext_next)))
+                    break;
+
+ if (bdrv_read(bs, ext_start_sector + ext_next.start_sector_abs , data1, 1))
+   errx(EINVAL, "error while reading");
+     }
+ }else
+ {
+   ;//printf("is a main partition......\n");
+ }
+    }
+    
+    return k;
+}
+
+
+
+
+
+int find_partition(BlockDriverState *bs, int partition,
+                          off_t *offset, off_t *size)
+{
+    struct partition_record mbr[4];
+    uint8_t data[512];
+    int i;
+    int ext_partnum = 4;
+
+
+    if (bdrv_read(bs, 0, data, 1))
+        errx(EINVAL, "error while reading");
+
+    if (data[510] != 0x55 || data[511] != 0xaa) 
+    {
+        errno = -EINVAL;
+        return -1;
+    }
+    
+    int k = 0;
+    for (i = 0; i < 4; i++) 
+    {
+        read_partition(&data[446 + 16 * i], &mbr[i]);
+
+        if (!mbr[i].nb_sectors_abs)
+            continue;
+ //printf("the %d partition:", i+1);
+
+        if (mbr[i].system == 0xF || mbr[i].system == 0x5) 
+ {
+   //printf("is a extend partition......\n");
+            struct partition_record ext[10];
+            uint8_t data1[512];
+            int j = 0;
+
+            if (bdrv_read(bs, mbr[i].start_sector_abs, data1, 1))
+                errx(EINVAL, "error while reading");
+     
+     uint32_t ext_start_sector = mbr[i].start_sector_abs;
+     struct partition_record ext_next = {0};
+            while (1) 
+     {
+         read_partition(&data1[446 + 16 * 0], &ext[j]);
+ printf("start=%u, total=%u, system=0x%x\t",
+        ext[j].start_sector_abs, ext[j].nb_sectors_abs, ext[j].system);
+ printf("the %dth partition is a logical part\n", ext_partnum + j + 1);
+
+ if(0 != ext[j].nb_sectors_abs) 
+ {
+   if ((ext_partnum + j + 1) == partition) 
+   {
+     ext[j].start_sector_abs +=  ext_start_sector;
+     if(j > 0)
+       ext[j].start_sector_abs += ext_next.start_sector_abs;
+     *offset = (uint64_t)ext[j].start_sector_abs << 9;
+     *size = (uint64_t)ext[j].nb_sectors_abs << 9;
+     return 0;
+   }
+   j++;
+         }
+
+ read_partition(&data1[446 + 16 * 1], &ext_next);
+ if (is_full_zero(&ext_next, sizeof(ext_next)))
+                    break;
+ //ext_start_sector += ext_next.start_sector_abs;
+ if (bdrv_read(bs, ext_start_sector + ext_next.start_sector_abs, data1, 1))
+     errx(EINVAL, "error while reading");
+     }
+            
+        } 
+ else 
+ {
+   //printf("is a main partition......\n");
+     if ((i + 1) == partition) 
+     {
+       *offset = (uint64_t)mbr[i].start_sector_abs << 9;
+       *size = (uint64_t)mbr[i].nb_sectors_abs << 9;
+       return 0;
+     }
+ }
+    }
+
+    errno = -ENOENT;
+    return -1;
+}
+
+///////////////////////////////////////////////////////
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/partition.h xen-4.1.2-b/tools/ioemu-qemu-xen/partition.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/partition.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/partition.h 2012-12-28 16:02:41.015940225 +0800
@@ -0,0 +1,46 @@
+#ifndef _PARTITION_H
+#define _PARTITION_H
+
+#include <stdint.h>
+
+typedef struct partition_record
+{
+    uint8_t bootable;
+    uint8_t start_head;
+    uint32_t start_cylinder;
+    uint8_t start_sector;
+    uint8_t system;
+    uint8_t end_head;
+    uint8_t end_cylinder;
+    uint8_t end_sector;
+    uint32_t start_sector_abs;
+    uint32_t nb_sectors_abs;
+} __attribute__ ((packed)) part_record_t;
+
+
+
+typedef enum
+  {
+    FS_UNKNOWN = 0,
+    FS_FAT,
+    FS_NTFS
+  }FS_TYPE;
+
+typedef struct ls_partition
+{
+  part_record_t part;
+  int id;
+  FS_TYPE fs_type;
+}ls_partition_t;
+
+
+char* judge_fs(ls_partition_t* pt);
+
+#include "block_int.h"
+int enum_partition(BlockDriverState *bs, ls_partition_t* parts);
+
+int find_partition(BlockDriverState *bs, int partition,
+    off_t *offset, off_t *size);
+
+
+#endif
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/qemu-img.c xen-4.1.2-b/tools/ioemu-qemu-xen/qemu-img.c
--- xen-4.1.2-a/tools/ioemu-qemu-xen/qemu-img.c 2011-02-12 01:54:51.000000000 +0800
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/qemu-img.c 2012-12-28 16:02:41.016932622 +0800
@@ -20,23 +20,35 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
 #include "qemu-common.h"
 #include "osdep.h"
 #include "block_int.h"
 #include <assert.h>
+#include <err.h>
+
+
+#include "partition.h"
+#include "fs-comm.h"
+#include "fat.h"
+#include "ntfs.h"
+#include "misc.h"
+
+
+
 
 #ifdef _WIN32
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #endif
 
 /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
+#define MAX_PARTITIONS    20
 #define BRDV_O_FLAGS BDRV_O_CACHE_WB
 
 static void QEMU_NORETURN error(const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
     fprintf(stderr, "qemu-img: ");
     vfprintf(stderr, fmt, ap);
@@ -53,16 +65,18 @@ static void format_print(void *opaque, c
 /* Please keep in synch with qemu-img.texi */
 static void help(void)
 {
     printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
            "usage: qemu-img command [command options]\n"
            "QEMU disk image utility\n"
            "\n"
            "Command syntax:\n"
+           "  ls [-v] [[-l] -d directory] imgfile\n"
+           "  cat [-v] -f file imgfile\n"
            "  create [-e] [-6] [-b base_image] [-f fmt] filename [size]\n"
            "  commit [-f fmt] filename\n"
            "  convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
            "  info [-f fmt] filename\n"
            "  snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename\n"
            "\n"
            "Command parameters:\n"
            "  'filename' is a disk image filename\n"
@@ -209,16 +223,343 @@ static BlockDriverState *bdrv_new_open(c
         if (read_password(password, sizeof(password)) < 0)
             error("No password given");
         if (bdrv_set_key(bs, password) < 0)
             error("invalid password");
     }
     return bs;
 }
 
+static void get_partition_path(const char *dir, int *which_part, char **path)
+{
+    static char full_path[512];
+    char part[5]={};
+
+    strncpy(full_path, dir, 512);
+    full_path[511] = '\0';
+
+    //限制以/开头 结尾
+    char *p1 = full_path + 1;
+    char *p2 = strchr(full_path + 1, '/');
+    if(!p2)
+    {
+        errx(1, "check the file path!\n");
+    }
+
+    *path = p2;
+    strncpy(part, p1, p2-p1);
+    *which_part = atoi(part);
+}
+
+typedef struct grub_fs
+{
+    grub_open open;
+    grub_ls ls;
+    grub_read read;
+    grub_close close;
+}grub_fs_t;
+
+static grub_fs_t grub_fs_plug[10] = {};
+
+static void grub_fs_plugin(void)
+{
+  grub_fs_plug[FS_FAT].open = grub_fat_open;
+  grub_fs_plug[FS_FAT].read = grub_fat_read;
+  grub_fs_plug[FS_FAT].close = grub_fat_close;
+  grub_fs_plug[FS_FAT].ls = grub_fat_ls;
+
+  grub_fs_plug[FS_NTFS].open = grub_ntfs_open;
+  grub_fs_plug[FS_NTFS].read = grub_ntfs_read;
+  grub_fs_plug[FS_NTFS].close = grub_ntfs_close;
+  grub_fs_plug[FS_NTFS].ls = grub_ntfs_ls;
+}
+
+static int img_ls(int argc, char **argv)
+{
+    int c = -1;
+    char *imgfile = NULL;
+    char *dir = NULL;
+    char verbose = 0;
+    struct ls_ctrl ctrl={};
+
+    for(;;) 
+    {
+        c = getopt(argc, argv, "d:hlv");
+        if (c == -1)
+            break;
+
+        switch(c) 
+        {
+            case 'v':
+                verbose = 1;
+                break;
+            case 'l':
+                ctrl.detail = 1;
+                break;
+            case 'h':
+                help();
+                break;
+            case 'd':
+                dir = optarg;
+                break;
+            default:
+                break;
+        }
+    }
+    
+    imgfile = argv[optind++];
+    
+    if (optind > argc)
+      help();
+    
+    BlockDriverState *bs = bdrv_new("");
+    if(!bs)
+        error("Not enough memory for bdrv_new\n");
+    if(bdrv_open(bs, imgfile, BRDV_O_FLAGS) < 0)
+        error("Could not open '%s'\n", imgfile);
+    
+    off_t off_bytes = 0;
+    off_t size_bytes = 0;
+    int i = 0;
+    ls_partition_t* parts = (ls_partition_t*)malloc(MAX_PARTITIONS * sizeof(ls_partition_t));
+    int count = enum_partition(bs, parts);
+    
+    if(!dir)
+    {
+        //find_partition(bs, 15, &off_bytes, &size_bytes);
+        printf("id\tactive\ttype\tfs\tstart_sector\ttotal_sectors\n");
+        for(i = 0; i < count; i++)
+        {
+            printf("%d\t%s\t%s\t%s\t%u\t%u\n", 
+                   parts[i].id, 
+                   parts[i].part.bootable==0x80 ? "active" : "none-active",
+                   (parts[i].part.system==0x0f || parts[i].part.system==0x05) ? "extend" : (parts[i].id>=5 ? "logical" : "primary"),
+                   judge_fs(&parts[i]),
+                   parts[i].part.start_sector_abs,
+                   parts[i].part.nb_sectors_abs
+                   );
+        }
+
+        goto fail;
+    }
+    else
+    {
+        grub_fs_plugin();
+      
+        grub_file_t file = NULL;
+        char *path = NULL;
+        int which_part = 1;
+      
+        file = (grub_file_t)malloc(sizeof(*file));
+        file->bs = bs;
+        file->data = "">
+
+        if('/' != dir[strlen(dir) - 1])
+            strcat(dir, "/");
+
+        get_partition_path(dir, &which_part, &path);
+        if(which_part < 1 || which_part > count)
+        {
+            fprintf(stderr, "error: check the partition number!\n");
+            goto fail;
+        }
+
+        file->part_off_sector = parts[which_part - 1].part.start_sector_abs;
+        ctrl.dirname = dir;
+        printf("【name\t"
+               "size(bytes)\t"
+               "dir?\t"
+               "date\t"
+               "time】\n");
+
+        judge_fs(&parts[which_part - 1]);
+        FS_TYPE fs_type = parts[which_part - 1].fs_type;
+        if (fs_type == FS_UNKNOWN) 
+        {
+            errx(1, "unknown file system!\n");
+        }
+
+        grub_fs_plug[fs_type].ls(file, path, NULL, (void*)&ctrl);
+        file->data ? free(file->data) : 0;
+        free(file);
+    }
+    
+    
+  fail:
+    bdrv_delete(bs);
+    free(parts);
+    return 0;
+}
+
+
+
+static int img_cat(int argc, char **argv)
+{
+    int c = -1;
+    char *imgfile = NULL;
+    char *filename = NULL;
+    char verbose = 0;
+
+    for(;;) {
+        c = getopt(argc, argv, "f:hv");
+        if (c == -1)
+            break;
+        switch(c) {
+            case 'v':
+                verbose = 1;
+                break;
+            case 'h':
+                help();
+                break;
+            case 'f':
+                filename = optarg;
+                break;
+            default:
+                break;
+        }
+    }
+    
+    imgfile = argv[optind++];
+    if (optind > argc)
+        help();
+
+    
+    if(!filename)
+    {
+        printf("error: specific the file to show!\n");
+        return -1;
+    }
+        
+    BlockDriverState *bs = bdrv_new("");
+    if(!bs)
+        errx(-1, "Not enough memory for bdrv_new\n");
+    if(bdrv_open(bs, imgfile, BRDV_O_FLAGS) < 0)
+        errx(-1, "Could not open %s\n", imgfile);
+    
+
+    uint buf_size = 4096;
+    char* buf = (char*)malloc(buf_size);
+    off_t off_bytes = 0;
+    off_t size_bytes = 0;
+    int i = 0;
+    ls_partition_t *parts = (ls_partition_t*)malloc(MAX_PARTITIONS * sizeof(ls_partition_t));
+    int count = enum_partition(bs, parts);
+    
+       
+    {
+        grub_fs_plugin();
+
+        grub_file_t file = NULL;
+        char *path = NULL;
+        int which_part = 1;
+      
+        file = (grub_file_t)malloc(sizeof(*file));
+        file->bs = bs;
+        file->data = "">
+      
+        char* p = strchr(filename, '/');
+        if(!p)
+        {
+            errx(-1, "please check the file path!\n");
+        }
+        else
+        {
+            p = strchr(p, '/');
+            if(!p) errx(-1, "check the file path!!\n");
+        }
+   
+        get_partition_path(filename, &which_part, &path);
+        DBG("part=%d, path=%s", which_part, path);
+        if(which_part < 1 || which_part > count)
+        {
+            printf("error: check the partition number!\n");
+            goto fail;
+        }
+        file->part_off_sector = parts[which_part - 1].part.start_sector_abs;
+        judge_fs(&parts[which_part - 1]);
+        FS_TYPE fs_type = parts[which_part - 1].fs_type;
+        (fs_type == FS_UNKNOWN) ? errx(1, "unknown file system!\n") : 0;
+        grub_fs_t grub_fs_plg = grub_fs_plug[fs_type];
+   
+        if(grub_fs_plg.open(file, path) == 0)
+        {
+            //printf("file size=%zd bytes\n", (file->size));
+   
+            grub_size_t len = file->size;
+            grub_off_t off = 0;
+            char  tmpfile[256]={};
+            strncpy(tmpfile, getenv("HOME"), sizeof(tmpfile));
+            tmpfile[sizeof(tmpfile) - 1] = '\0';
+            strcat(tmpfile, "/tmp.file");
+     
+            if(!buf)
+            {
+                perror("not enough memory!\n");
+                goto fail;
+            }
+            else
+            {
+                grub_size_t readed = 0;
+                grub_size_t left  = len;
+                grub_size_t total = 0;
+                FILE* f = fopen(tmpfile ,"w");
+                if(!f)
+                {
+                    perror("fopen error");
+                    goto fail;
+                }
+       
+       
+                (left > buf_size) ? (left = buf_size) : 0;
+                while((readed = grub_fs_plg.read(file, off, left, buf))
+                      && total <= len
+                      && readed > 0)
+                {
+                    DBG("readed=%zd", readed);
+                    total += fwrite(buf, 1, readed, f);
+                    off = total;
+                    left = len - total;
+                    (left <= buf_size) ? 0  : (left = buf_size);
+                    DBG("total=%zd", total);
+                };
+                fclose(f);
+       
+                if(total != len)
+                {
+                    perror("read error");
+                    goto fail;
+                }
+                else
+                {
+                    sprintf(buf, "cat %s", tmpfile);
+                    system(buf);
+  
+                }
+            }
+        }
+        else
+        {
+            printf("open failed!\n");
+        }
+      
+      
+        grub_fs_plg.close(file);
+        free(file);
+    }
+    
+    
+  fail:
+    free(buf);
+    bdrv_delete(bs);
+    free(parts);
+    return 0;
+}
+
+
+
 static int img_create(int argc, char **argv)
 {
     int c, ret, flags;
     const char *fmt = "raw";
     const char *filename;
     const char *base_filename = NULL;
     uint64_t size;
     const char *p;
@@ -850,16 +1191,17 @@ static void img_snapshot(int argc, char 
     }
 
     /* Cleanup */
     bdrv_delete(bs);
 }
 
 int main(int argc, char **argv)
 {
+  
     const char *cmd;
 
     bdrv_init();
     if (argc < 2)
         help();
     cmd = argv[1];
     argc--; argv++;
     if (!strcmp(cmd, "create")) {
@@ -867,13 +1209,19 @@ int main(int argc, char **argv)
     } else if (!strcmp(cmd, "commit")) {
         img_commit(argc, argv);
     } else if (!strcmp(cmd, "convert")) {
         img_convert(argc, argv);
     } else if (!strcmp(cmd, "info")) {
         img_info(argc, argv);
     } else if (!strcmp(cmd, "snapshot")) {
         img_snapshot(argc, argv);
-    } else {
+    } else if (!strcmp(cmd, "ls")) {
+        img_ls(argc, argv);    
+    } else if (!strcmp(cmd, "cat")) {
+        img_cat(argc, argv);
+    }
+    else {
         help();
     }
+    
     return 0;
 }
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/types.h xen-4.1.2-b/tools/ioemu-qemu-xen/types.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/types.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/types.h 2012-12-28 16:02:41.016932622 +0800
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2006,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER 1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P 4
+
+/* The size of long.  */
+#define GRUB_TARGET_SIZEOF_LONG 4
+
+/* i386 is little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#define GRUB_TARGET_I386 1
+
+#define GRUB_TARGET_MIN_ALIGN 1
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/x86_64/types.h xen-4.1.2-b/tools/ioemu-qemu-xen/x86_64/types.h
--- xen-4.1.2-a/tools/ioemu-qemu-xen/x86_64/types.h 1970-01-01 07:00:00.000000000 +0700
+++ xen-4.1.2-b/tools/ioemu-qemu-xen/x86_64/types.h 2012-12-28 16:02:41.017802371 +0800
@@ -0,0 +1,39 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER 1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P 8
+
+/* The size of long.  */
+#ifdef __MINGW32__
+#define GRUB_TARGET_SIZEOF_LONG 4
+#else
+#define GRUB_TARGET_SIZEOF_LONG 8
+#endif
+
+/* x86_64 is little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#define GRUB_TARGET_X86_64 1
+
+#define GRUB_TARGET_MIN_ALIGN 1
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]