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

Re: [Xen-devel] [PATCH] patch for listing and reading files from qcow2-formated image file (for xen-4.1.2)





On Sat, Jan 5, 2013 at 2:51 PM, 马磊 <aware.why@xxxxxxxxx> wrote:


On Fri, Dec 28, 2012 at 4:22 PM, 马磊 <aware.why@xxxxxxxxx> wrote:
Hi,
    The final effect is as follows:
    
[malei@xentest-4-1 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

[malei@xentest-4-1 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. 


How to submit a patch to the xen source trunk except through hg mecurial?
Does anybody ever go through such thing by sending the patch to the mail list?

Does anyone prefer this feature?!



Signed-off-by: Lei Ma (malei@xxxxxx)

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 "bean123ch@xxxxxxxxx"
+
+/* 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 "bean123ch@xxxxxxxxx"
+
+/* 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 */


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.