qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH] reading files from qcow2-formated image disk fo


From: Blue Swirl
Subject: Re: [Qemu-devel] [PATCH] reading files from qcow2-formated image disk for windows system
Date: Wed, 9 Jan 2013 21:37:54 +0000

On Wed, Jan 9, 2013 at 7:31 AM, 马磊 <address@hidden> wrote:
>
>
>>> Hi,
>>>     The final effect is as follows:
>>>
>>>
>>> address@hidden Fri Dec 28 ~/honeypot/xen/xen-4.1.2]$ qemu-img-xen cat
>>> -f /1/boot.ini ~/vm-check.img
>>> [boot loader]
>>> timeout=30
>>> default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
>>> [operating systems]
>>> multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP
>>> Professional" /noexecute=optin /fastdetect
>>>
>>> address@hidden Fri Dec 28 ~/honeypot/xen/xen-4.1.2]$ qemu-img-xen ls
>>> -l -d /1/ ~/vm-check.img
>>> 【name                 size(bytes) dir?      date
>>> create-time】
>>> AUTOEXEC.BAT 0                file 2010-12-22        17:30:37
>>> boot.ini               211                file 2010-12-23        01:24:41
>>> bootfont.bin  322730                file 2004-11-23        20:00:00
>>>
>>>
>>>
>>> As you see above, the patch add two sub-commands for qemu-img-xen:cat and
>>> ls.
>>>
>>> For details in the patch, please check the attachment.
>>>
>>>
>
> Does anyone prefer this feature?!

Nice feature, but this approach would just clutter QEMU and give only
readonly FAT or NTFS support. I think a more generally useful approach
would be to use NBD or iSCSI to export the block device data from the
image file (qemu-nbd already exists) and then make a tool that uses
some combination of NBD/iSCSI client, all GRUB file systems and FUSE
or other user space methods to access the contents of the filesystem.
Probably also UML with a simple guest agent could provide read/write
access to any file system that Linux supports.

>
>
>
> Signed-off-by: Lei Ma (address@hidden)
>
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/debug.c

Patches sent to qemu-devel should be based on qemu.git. Please also
read CODING_STYLE and HACKING files.

> 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 = 0;
> +  grub_uint32_t first_fat, magic;
> +  int64_t off_bytes = (int64_t)part_off_sector << GRUB_DISK_SECTOR_BITS;
> +
> +  if (! bs)
> +    goto fail;
> +
> +  data = (struct 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->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 = 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 = 0;
> +  char *p = (char *) name;
> +
> +
> +  data = grub_fat_mount (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 = data;
> +  file->size = data->file_size;
> +  return 0;
> +
> + fail:
> +  free(data);
> +  file->data = NULL;
> +  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 = 0;
> +  grub_size_t len;
> +  char *dirname = 0;
> +  char *p;
> +
> +  data = grub_fat_mount (file->bs, file->part_off_sector);
> +  if (! data)
> +    goto fail;
> +
> +  file->data = 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 = NULL;
> +
> +  return g_err;
> +}
> +
> +
> +grub_err_t grub_fat_close(grub_file_t file)
> +{
> +  free(file->data);
> +  return g_err;
> +}
> +
> +
> +grub_ssize_t grub_fat_read(grub_file_t file, grub_off_t offset,
> +    grub_size_t len, char *buf)
> +{
> +  return grub_fat_read_data(file->bs, file->data, NULL, NULL, offset, len,
> buf);
> +}
> +
> +
> +
> +
> +
> +
> +
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fat.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/fat.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/fat.h 1970-01-01 07:00:00.000000000
> +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/fat.h 2012-12-28 16:02:41.002938019
> +0800
> @@ -0,0 +1,160 @@
> +#ifndef FS_FAT_H
> +#define FS_FAT_H
> +
> +
> +#include "fs-types.h"
> +#include "block_int.h"
> +#include "fs-comm.h"
> +#include "grub_err.h"
> +
> +
> +#define GRUB_DISK_SECTOR_BITS      9
> +#define GRUB_FAT_DIR_ENTRY_SIZE 32
> +
> +#define GRUB_FAT_ATTR_READ_ONLY 0x01
> +#define GRUB_FAT_ATTR_HIDDEN 0x02
> +#define GRUB_FAT_ATTR_SYSTEM 0x04
> +#define GRUB_FAT_ATTR_VOLUME_ID 0x08
> +#define GRUB_FAT_ATTR_DIRECTORY 0x10
> +#define GRUB_FAT_ATTR_ARCHIVE 0x20
> +
> +#define GRUB_FAT_MAXFILE 256
> +
> +#define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \
> +  | GRUB_FAT_ATTR_HIDDEN \
> +  | GRUB_FAT_ATTR_SYSTEM \
> +  | GRUB_FAT_ATTR_VOLUME_ID)
> +#define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \
> +  | GRUB_FAT_ATTR_HIDDEN \
> +  | GRUB_FAT_ATTR_SYSTEM \
> +  | GRUB_FAT_ATTR_DIRECTORY \
> +  | GRUB_FAT_ATTR_ARCHIVE \
> +  | GRUB_FAT_ATTR_VOLUME_ID)
> +
> +struct grub_fat_bpb
> +{
> +  grub_uint8_t jmp_boot[3];
> +  grub_uint8_t oem_name[8];
> +  grub_uint16_t bytes_per_sector;
> +  grub_uint8_t sectors_per_cluster;
> +  grub_uint16_t num_reserved_sectors;
> +  grub_uint8_t num_fats;
> +  grub_uint16_t num_root_entries;
> +  grub_uint16_t num_total_sectors_16;
> +  grub_uint8_t media;
> +  grub_uint16_t sectors_per_fat_16;
> +  grub_uint16_t sectors_per_track;
> +  grub_uint16_t num_heads;
> +  grub_uint32_t num_hidden_sectors;
> +  grub_uint32_t num_total_sectors_32;
> +  union
> +  {
> +    struct
> +    {
> +      grub_uint8_t num_ph_drive;
> +      grub_uint8_t reserved;
> +      grub_uint8_t boot_sig;
> +      grub_uint32_t num_serial;
> +      grub_uint8_t label[11];
> +      grub_uint8_t fstype[8];
> +    } __attribute__ ((packed)) fat12_or_fat16;
> +    struct
> +    {
> +      grub_uint32_t sectors_per_fat_32;
> +      grub_uint16_t extended_flags;
> +      grub_uint16_t fs_version;
> +      grub_uint32_t root_cluster;
> +      grub_uint16_t fs_info;
> +      grub_uint16_t backup_boot_sector;
> +      grub_uint8_t reserved[12];
> +      grub_uint8_t num_ph_drive;
> +      grub_uint8_t reserved1;
> +      grub_uint8_t boot_sig;
> +      grub_uint32_t num_serial;
> +      grub_uint8_t label[11];
> +      grub_uint8_t fstype[8];
> +    } __attribute__ ((packed)) fat32;
> +  } __attribute__ ((packed)) version_specific;
> +} __attribute__ ((packed));
> +
> +struct grub_fat_dir_entry
> +{
> +  grub_uint8_t name[11];
> +  grub_uint8_t attr;
> +  grub_uint8_t nt_reserved;
> +  grub_uint8_t c_time_tenth;
> +  grub_uint16_t c_time;
> +  grub_uint16_t c_date;
> +  grub_uint16_t a_date;
> +  grub_uint16_t first_cluster_high;
> +  grub_uint16_t w_time;
> +  grub_uint16_t w_date;
> +  grub_uint16_t first_cluster_low;
> +  grub_uint32_t file_size;
> +} __attribute__ ((packed));
> +
> +struct grub_fat_long_name_entry
> +{
> +  grub_uint8_t id;
> +  grub_uint16_t name1[5];
> +  grub_uint8_t attr;
> +  grub_uint8_t reserved;
> +  grub_uint8_t checksum;
> +  grub_uint16_t name2[6];
> +  grub_uint16_t first_cluster;
> +  grub_uint16_t name3[2];
> +} __attribute__ ((packed));
> +
> +struct grub_fat_data
> +{
> +  int logical_sector_bits;
> +  grub_uint32_t num_sectors;
> +
> +  grub_uint32_t fat_sector;
> +  grub_uint32_t sectors_per_fat;
> +  int fat_size;
> +
> +  grub_uint32_t root_cluster;
> +  grub_uint32_t root_sector;
> +  grub_uint32_t num_root_sectors;
> +
> +  int cluster_bits;
> +  grub_uint32_t cluster_eof_mark;
> +  grub_uint32_t cluster_sector;
> +  grub_uint32_t num_clusters;
> +
> +  grub_uint8_t attr;
> +  grub_ssize_t file_size;
> +  grub_uint32_t file_cluster;
> +  grub_uint32_t cur_cluster_num;
> +  grub_uint32_t cur_cluster;
> +
> +  grub_uint32_t uuid;
> +};
> +
> +
> +
> +
> +
> +
> +
> +struct grub_fat_data*
> +grub_fat_mount (BlockDriverState *bs, grub_uint32_t part_off_sector);
> +
> +grub_err_t
> +grub_fat_open (grub_file_t file, const char *name);
> +
> +grub_err_t
> +grub_fat_ls (grub_file_t file, const char *path,
> +       int (*hook) (const char *filename,
> +    const struct grub_dirhook_info *info,
> +    void *closure),
> +      void *closure);
> +
> +grub_err_t grub_fat_close(grub_file_t file);
> +
> +grub_ssize_t grub_fat_read(grub_file_t file, grub_off_t offset,
> +   grub_size_t len, char *buf);
> +
> +
> +#endif
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fs-comm.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/fs-comm.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/fs-comm.h 1970-01-01 07:00:00.000000000
> +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/fs-comm.h 2012-12-28 16:02:41.003846897
> +0800
> @@ -0,0 +1,60 @@
> +#ifndef _FS_COMM_H
> +#define _FS_COMM_H
> +
> +#include "fs-types.h"
> +#include "block_int.h"
> +#include "grub_err.h"
> +#include "debug.h"
> +
> +typedef struct  grub_file
> +{
> +  void *data;
> +  BlockDriverState *bs;
> +  uint32_t part_off_sector;
> +  grub_size_t size;
> +  grub_off_t offset;
> +  /* This is called when a sector is read. Used only for a disk device.  */
> +  void (*read_hook) (grub_disk_addr_t sector,
> +      unsigned offset, unsigned length, void *closure);
> +  void *closure;
> +}*grub_file_t;
> +
> +struct grub_dirhook_info
> +{
> +  unsigned dir:1;
> +  unsigned mtimeset:1;
> +  unsigned case_insensitive:1;
> +  grub_uint32_t mtime;    //(date | time)
> +  grub_uint32_t filesize;
> +  grub_uint64_t filesize_ntfs;
> +  grub_uint64_t time_ntfs;
> +};
> +
> +struct ls_ctrl
> +{
> +  unsigned detail:1;
> +  char* dirname;
> +};
> +
> +
> +
> +
> +typedef grub_err_t
> +(*grub_open) (grub_file_t file, const char *name);
> +
> +typedef grub_err_t
> +(*grub_ls) (grub_file_t file, const char *path,
> +       int (*hook) (const char *filename,
> +    const struct grub_dirhook_info *info,
> +    void *closure),
> +      void *closure);
> +
> +typedef grub_err_t
> +(*grub_close) (grub_file_t file);
> +
> +typedef grub_ssize_t
> +(*grub_read)(grub_file_t file, grub_off_t offset,
> +   grub_size_t len, char *buf);
> +
> +
> +#endif
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fshelp.c
> xen-4.1.2-b/tools/ioemu-qemu-xen/fshelp.c
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/fshelp.c 1970-01-01 07:00:00.000000000
> +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/fshelp.c 2012-12-28 16:02:41.004932457
> +0800
> @@ -0,0 +1,362 @@
> +/* fshelp.c -- Filesystem helper functions */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2004,2005,2006,2007,2008  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "err.h"
> +#include "misc.h"
> +#include "block_int.h"
> +#include "fshelp.h"
> +#include "ntfs.h"
> +#include "debug.h"
> +
> +struct grub_fshelp_find_file_closure
> +{
> +  grub_fshelp_node_t rootnode;
> +  int (*iterate_dir) (grub_fshelp_node_t dir,
> +       int (*hook)
> +       (const char *filename,
> +        enum grub_fshelp_filetype filetype,
> +        grub_fshelp_node_t node, void *closure),
> +       void *closure);
> +  void *closure;
> +  char *(*read_symlink) (grub_fshelp_node_t node);
> +  int symlinknest;
> +  enum grub_fshelp_filetype foundtype;
> +  grub_fshelp_node_t currroot;
> +};
> +
> +static void
> +free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_closure
> *c)
> +{
> +  if (node != c->rootnode && node != c->currroot)
> +    grub_free (node);
> +}
> +
> +struct find_file_closure
> +{
> +  char *name;
> +  enum grub_fshelp_filetype *type;
> +  grub_fshelp_node_t *oldnode;
> +  grub_fshelp_node_t *currnode;
> +};
> +
> +static int
> +iterate (const char *filename,
> +  enum grub_fshelp_filetype filetype,
> +  grub_fshelp_node_t node,
> +  void *closure)
> +{
> +  struct find_file_closure *c = closure;
> +  DBG("list_file hooked by fshelp:iterate(), filename=%s", filename);
> +  if (filetype == GRUB_FSHELP_UNKNOWN ||
> +      (grub_strcmp (c->name, filename) &&
> +       (! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
> + grub_strncasecmp (c->name, filename, GRUB_LONG_MAX))))
> +    {
> +      DBG("not match!!!>>>>>>");
> +      grub_free (node);
> +      return 0;
> +    }
> +
> +  /* The node is found, stop iterating over the nodes.  */
> +  *(c->type) = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
> +  *(c->oldnode) = *(c->currnode);
> +  *(c->currnode) = node;
> +  DBG("found!!>>>>>>");
> +  return 1;
> +}
> +
> +static grub_err_t
> +find_file (const char *currpath, grub_fshelp_node_t currroot,
> +    grub_fshelp_node_t *currfound,
> +    struct grub_fshelp_find_file_closure *c)
> +{
> +  char fpath[grub_strlen (currpath) + 1];
> +  char *name = fpath;
> +  char *next;
> +  enum grub_fshelp_filetype type = GRUB_FSHELP_DIR;
> +  grub_fshelp_node_t currnode = currroot;
> +  grub_fshelp_node_t oldnode = currroot;
> +
> +  c->currroot = currroot;
> +
> +  grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1);
> +
> +  /* Remove all leading slashes.  */
> +  while (*name == '/')
> +    name++;
> +
> +  if (! *name)
> +    {
> +      *currfound = currnode;
> +      return 0;
> +    }
> +
> +  for (;;)
> +    {
> +      int found;
> +      struct find_file_closure cc;
> +
> +      /* Extract the actual part from the pathname.  */
> +      next = grub_strchr (name, '/');
> +      if (next)
> + {
> +   /* Remove all leading slashes.  */
> +   while (*next == '/')
> +     *(next++) = '\0';
> + }
> +
> +      /* At this point it is expected that the current node is a
> +  directory, check if this is true.  */
> +      if (type != GRUB_FSHELP_DIR)
> + {
> +   free_node (currnode, c);
> +   return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
> + }
> +
> +      DBG("find_file_closure cc.name=【%s】", name);
> +      cc.name = name;
> +      cc.type = &type;
> +      cc.oldnode = &oldnode;
> +      cc.currnode = &currnode;
> +      /* Iterate over the directory.  */
> +      DBG("******fshelp:find_file hooked by \'grub_ntfs_iterate_dir\',"
> +   "nested another hook \'fshelp:iterator\'");
> +      found = c->iterate_dir (currnode, iterate, &cc);
> +      if (! found)
> + {
> +   if (grub_errno)
> +     return grub_errno;
> +
> +   break;
> + }
> +
> +      /* Read in the symlink and follow it.  */
> +      if (type == GRUB_FSHELP_SYMLINK)
> + {
> +   char *symlink;
> +
> +   /* Test if the symlink does not loop.  */
> +   if (++(c->symlinknest) == 8)
> +     {
> +       free_node (currnode, c);
> +       free_node (oldnode, c);
> +       return grub_error (GRUB_ERR_SYMLINK_LOOP,
> +  "too deep nesting of symlinks");
> +     }
> +
> +   symlink = c->read_symlink (currnode);
> +   free_node (currnode, c);
> +
> +   if (!symlink)
> +     {
> +       free_node (oldnode, c);
> +       return grub_errno;
> +     }
> +
> +   /* The symlink is an absolute path, go back to the root inode.  */
> +   if (symlink[0] == '/')
> +     {
> +       free_node (oldnode, c);
> +       oldnode = c->rootnode;
> +     }
> +
> +   /* Lookup the node the symlink points to.  */
> +   find_file (symlink, oldnode, &currnode, c);
> +   type = c->foundtype;
> +   grub_free (symlink);
> +
> +   if (grub_errno)
> +     {
> +       free_node (oldnode, c);
> +       return grub_errno;
> +     }
> + }
> +
> +      free_node (oldnode, c);
> +
> +      /* Found the node!  */
> +      if (! next || *next == '\0')
> + {
> +   *currfound = currnode;
> +   c->foundtype = type;
> +   return 0;
> + }
> +
> +      name = next;
> +    }
> +
> +  return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
> +}
> +
> +/* Lookup the node PATH.  The node ROOTNODE describes the root of the
> +   directory tree.  The node found is returned in FOUNDNODE, which is
> +   either a ROOTNODE or a new malloc'ed node.  ITERATE_DIR is used to
> +   iterate over all directory entries in the current node.
> +   READ_SYMLINK is used to read the symlink if a node is a symlink.
> +   EXPECTTYPE is the type node that is expected by the called, an
> +   error is generated if the node is not of the expected type.  Make
> +   sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
> +   because GCC has a nasty bug when using regparm=3.  */
> +grub_err_t
> +grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
> +        grub_fshelp_node_t *foundnode,
> +        int (*iterate_dir) (grub_fshelp_node_t dir,
> +    int (*hook)
> +    (const char *filename,
> +     enum grub_fshelp_filetype filetype,
> +     grub_fshelp_node_t node,
> +     void *closure),
> +    void *closure),
> +        void *closure,
> +        char *(*read_symlink) (grub_fshelp_node_t node),
> +        enum grub_fshelp_filetype expecttype)
> +{
> +  grub_err_t err;
> +  struct grub_fshelp_find_file_closure c;
> +
> +  c.rootnode = rootnode;
> +  c.iterate_dir = iterate_dir;
> +  c.closure = closure;
> +  c.read_symlink = read_symlink;
> +  c.symlinknest = 0;
> +  c.foundtype = GRUB_FSHELP_DIR;
> +
> +  if (!path || path[0] != '/')
> +    {
> +      grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
> +      return grub_errno;
> +    }
> +
> +
> +  DBG("going to find_file\n");
> +  err = find_file (path, rootnode, foundnode, &c);
> +  if (err)
> +    return err;
> +
> +  /* Check if the node that was found was of the expected type.  */
> +  if (expecttype == GRUB_FSHELP_REG && c.foundtype != expecttype)
> +    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file");
> +  else if (expecttype == GRUB_FSHELP_DIR && c.foundtype != expecttype)
> +    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
> +
> +  return 0;
> +}
> +
> +/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
> +   beginning with the block POS.  READ_HOOK should be set before
> +   reading a block from the file.  GET_BLOCK is used to translate file
> +   blocks to disk blocks.  The file is FILESIZE bytes big and the
> +   blocks have a size of LOG2BLOCKSIZE (in log2).  */
> +grub_ssize_t
> +grub_fshelp_read_file (BlockDriverState* bs, grub_fshelp_node_t node,
> +        void (*read_hook) (grub_disk_addr_t sector,
> +   unsigned offset,
> +   unsigned length,
> +   void *closure),
> +        void *closure,
> +        grub_off_t pos, grub_size_t len, char *buf,
> +        grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
> +       grub_disk_addr_t block),
> +        grub_off_t filesize, int log2blocksize)
> +{
> +  grub_disk_addr_t i, blockcnt;
> +  grub_off_t off_bytes;
> +  int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
> +
> +  /* Adjust LEN so it we can't read past the end of the file.  */
> +  if (pos + len > filesize)
> +    len = filesize - pos;
> +
> +  blockcnt = ((len + pos) + blocksize - 1) >>
> +    (log2blocksize + GRUB_DISK_SECTOR_BITS);
> +
> +  for (i = pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS); i < blockcnt;
> i++)
> +    {
> +      grub_disk_addr_t blknr;
> +      int blockoff = pos & (blocksize - 1);
> +      int blockend = blocksize;
> +
> +      int skipfirst = 0;
> +
> +      blknr = get_block (node, i);
> +      if (grub_errno)
> + return -1;
> +
> +      blknr = blknr << log2blocksize;
> +      off_bytes = blknr << GRUB_DISK_SECTOR_BITS;
> +
> +      /* Last block.  */
> +      if (i == blockcnt - 1)
> + {
> +   blockend = (len + pos) & (blocksize - 1);
> +
> +   /* The last portion is exactly blocksize.  */
> +   if (! blockend)
> +     blockend = blocksize;
> + }
> +
> +      /* First block.  */
> +      if (i == (pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS)))
> + {
> +   skipfirst = blockoff;
> +   blockend -= skipfirst;
> + }
> +
> +      /* If the block number is 0 this block is not stored on disk but
> +  is zero filled instead.  */
> +      if (blknr)
> + {
> +   //bs->read_hook = read_hook;
> +   //bs->closure = closure;
> +
> +   bdrv_pread_from_lcn_of_volum(bs, off_bytes + skipfirst,
> +       buf, blockend);
> +   //bs->read_hook = 0;
> +   if (grub_errno)
> +     return -1;
> + }
> +      else
> + grub_memset (buf, 0, blockend);
> +
> +      buf += blocksize - skipfirst;
> +    }
> +
> +  return len;
> +}
> +
> +unsigned int
> +grub_fshelp_log2blksize (unsigned int blksize, unsigned int *pow)
> +{
> +  int mod;
> +
> +  *pow = 0;
> +  while (blksize > 1)
> +    {
> +      mod = blksize - ((blksize >> 1) << 1);
> +      blksize >>= 1;
> +
> +      /* Check if it really is a power of two.  */
> +      if (mod)
> + return grub_error (GRUB_ERR_BAD_NUMBER,
> +    "the blocksize is not a power of two");
> +      (*pow)++;
> +    }
> +
> +  return GRUB_ERR_NONE;
> +}
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fshelp.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/fshelp.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/fshelp.h 1970-01-01 07:00:00.000000000
> +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/fshelp.h 2012-12-28 16:02:41.004932457
> +0800
> @@ -0,0 +1,86 @@
> +/* fshelp.h -- Filesystem helper functions */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2004,2005,2006,2007,2008  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_FSHELP_HEADER
> +#define GRUB_FSHELP_HEADER 1
> +
> +#include "fs-types.h"
> +#include "grub_err.h"
> +#include "block_int.h"
> +typedef struct grub_fshelp_node *grub_fshelp_node_t;
> +
> +#define GRUB_FSHELP_CASE_INSENSITIVE 0x100
> +#define GRUB_FSHELP_TYPE_MASK 0xff
> +#define GRUB_FSHELP_FLAGS_MASK 0x100
> +
> +enum grub_fshelp_filetype
> +  {
> +    GRUB_FSHELP_UNKNOWN,
> +    GRUB_FSHELP_REG,
> +    GRUB_FSHELP_DIR,
> +    GRUB_FSHELP_SYMLINK
> +  };
> +
> +/* Lookup the node PATH.  The node ROOTNODE describes the root of the
> +   directory tree.  The node found is returned in FOUNDNODE, which is
> +   either a ROOTNODE or a new malloc'ed node.  ITERATE_DIR is used to
> +   iterate over all directory entries in the current node.
> +   READ_SYMLINK is used to read the symlink if a node is a symlink.
> +   EXPECTTYPE is the type node that is expected by the called, an
> +   error is generated if the node is not of the expected type.  Make
> +   sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
> +   because GCC has a nasty bug when using regparm=3.  */
> +grub_err_t grub_fshelp_find_file (const char *path,
> +   grub_fshelp_node_t rootnode,
> +   grub_fshelp_node_t *foundnode,
> +   int (*iterate_dir)
> +   (grub_fshelp_node_t dir,
> +    int (*hook)
> +    (const char *filename,
> +     enum grub_fshelp_filetype filetype,
> +     grub_fshelp_node_t node,
> +     void *closure),
> +    void *closure),
> +   void *closure,
> +   char *(*read_symlink) (grub_fshelp_node_t node),
> +   enum grub_fshelp_filetype expect);
> +
> +
> +/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
> +   beginning with the block POS.  READ_HOOK should be set before
> +   reading a block from the file.  GET_BLOCK is used to translate file
> +   blocks to disk blocks.  The file is FILESIZE bytes big and the
> +   blocks have a size of LOG2BLOCKSIZE (in log2).  */
> +grub_ssize_t grub_fshelp_read_file (BlockDriverState* bs,
> grub_fshelp_node_t node,
> +     void (*read_hook)
> +     (grub_disk_addr_t sector,
> +      unsigned offset,
> +      unsigned length,
> +      void *closure),
> +     void *closure,
> +     grub_off_t pos, grub_size_t len, char *buf,
> +     grub_disk_addr_t (*get_block)
> +     (grub_fshelp_node_t node,
> +      grub_disk_addr_t block),
> +     grub_off_t filesize, int log2blocksize);
> +
> +unsigned int grub_fshelp_log2blksize (unsigned int blksize,
> +       unsigned int *pow);
> +
> +#endif /* ! GRUB_FSHELP_HEADER */
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fs-time.c
> xen-4.1.2-b/tools/ioemu-qemu-xen/fs-time.c
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/fs-time.c 1970-01-01 07:00:00.000000000
> +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/fs-time.c 2012-12-28 16:02:41.005685798
> +0800
> @@ -0,0 +1,77 @@
> +#include "fs-time.h"
> +
> +
> +
> +static uint64_t div64(uint64_t a, uint32_t b, uint32_t c)
> +{
> +    union {
> +        uint64_t ll;
> +        struct {
> +#ifdef WORDS_BIGENDIAN
> +            uint32_t high, low;
> +#else
> +            uint32_t low, high;
> +#endif
> +        } l;
> +    } u, res;
> +    uint64_t rl, rh;
> +
> +    u.ll = a;
> +    rl = (uint64_t)u.l.low * (uint64_t)b;
> +    rh = (uint64_t)u.l.high * (uint64_t)b;
> +    rh += (rl >> 32);
> +    res.l.high = rh / c;
> +    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
> +    return res.ll;
> +}
> +
> +static uint64_t sub64(uint64_t a, uint64_t b)
> +{
> +  struct
> +  {
> +#ifdef WORDS_BIGENDIAN
> +            uint32_t high, low;
> +#else
> +            uint32_t low, high;
> +#endif
> +  }a1,b1,c;
> +
> +  a1.high = a>>32;
> +  a1.low = a&0xffffffff;
> +  b1.high = b>>32;
> +  b1.low = b&0xffffffff;
> +
> +  if(a1.high < b1.high)
> +    {
> +      c=b1;
> +      b1=a1;
> +      a1=c;
> +    }
> +
> +  a1.high -= b1.high;
> +  a1.low -= b1.low;
> +  if(a1.low & 0x80000000)
> +    {
> +      a1.low = (~(a1.low & 0x7fffffff))+1;
> +      a1.high -= 1;
> +    }
> +
> +  uint64_t ret = (uint64_t)a1.high<<32 | a1.low;
> +  return ret;
> +}
> +
> +struct tm* ntfs_utc2local(grub_uint64_t time, struct tm* ptm)
> +{
> +  //time_t time2 = sub64(time, NTFS_TIME_OFFSET);
> +  time_t time2 = time - NTFS_TIME_OFFSET;
> +  /*DBG("sizeof(int)=%d", sizeof(int));
> +  DBG("sizeof(short)=%d", sizeof(short));
> +  DBG("sizeof(long)=%d", sizeof(long));
> +  DBG("sizeof(long long)=%d", sizeof(unsigned long long));
> +  DBG("sizeof(time_t)=%d, time=%zu, time2=%zu", sizeof(time_t), time,
> time2);*/
> +  //time2 = div64(time2,1,10000000);
> +  time2 = time2 / 10000000;
> +  DBG("sizeof(time_t)=%d, time=%zu, time2=%zu", sizeof(time_t), time,
> time2);
> +  ////time2 = 0;//time(NULL);
> +  return localtime_r(&time2, ptm);
> +}
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fs-time.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/fs-time.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/fs-time.h 1970-01-01 07:00:00.000000000
> +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/fs-time.h 2012-12-28 16:02:41.005685798
> +0800
> @@ -0,0 +1,12 @@
> +#ifndef FS_TIME_H
> +#define FS_TIME_H
> +
> +#include <time.h>
> +#include "fs-comm.h"
> +#define NTFS_TIME_OFFSET ((grub_uint64_t)(369 * 365 + 89) * 24 * 3600 *
> 10000000)
> +
> +struct tm* ntfs_utc2local(grub_uint64_t time, struct tm* ptm);
> +
> +
> +#endif
> +
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/fs-types.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/fs-types.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/fs-types.h 1970-01-01
> 07:00:00.000000000 +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/fs-types.h 2012-12-28
> 16:02:41.006932417 +0800
> @@ -0,0 +1,234 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2002,2005,2006,2007,2008,2009  Free Software Foundation,
> Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_TYPES_HEADER
> +#define GRUB_TYPES_HEADER 1
> +
> +#include "grub-config.h"
> +#include "x86_64/types.h"
> +
> +#ifdef GRUB_UTIL
> +# define GRUB_CPU_SIZEOF_VOID_P SIZEOF_VOID_P
> +# define GRUB_CPU_SIZEOF_LONG SIZEOF_LONG
> +# ifdef WORDS_BIGENDIAN
> +#  define GRUB_CPU_WORDS_BIGENDIAN 1
> +# else
> +#  undef GRUB_CPU_WORDS_BIGENDIAN
> +# endif
> +#else /* ! GRUB_UTIL */
> +# define GRUB_CPU_SIZEOF_VOID_P GRUB_TARGET_SIZEOF_VOID_P
> +# define GRUB_CPU_SIZEOF_LONG GRUB_TARGET_SIZEOF_LONG
> +# ifdef GRUB_TARGET_WORDS_BIGENDIAN
> +#  define GRUB_CPU_WORDS_BIGENDIAN 1
> +# else
> +#  undef GRUB_CPU_WORDS_BIGENDIAN
> +# endif
> +#endif /* ! GRUB_UTIL */
> +
> +#if GRUB_CPU_SIZEOF_VOID_P != 4 && GRUB_CPU_SIZEOF_VOID_P != 8
> +# error "This architecture is not supported because sizeof(void *) != 4 and
> sizeof(void *) != 8"
> +#endif
> +
> +#ifndef GRUB_TARGET_WORDSIZE
> +# if GRUB_TARGET_SIZEOF_VOID_P == 4
> +#  define GRUB_TARGET_WORDSIZE 32
> +# elif GRUB_TARGET_SIZEOF_VOID_P == 8
> +#  define GRUB_TARGET_WORDSIZE 64
> +# endif
> +#endif
> +
> +/* Define various wide integers.  */
> +typedef signed char grub_int8_t;
> +typedef short grub_int16_t;
> +typedef int grub_int32_t;
> +#if GRUB_CPU_SIZEOF_LONG == 8
> +typedef long grub_int64_t;
> +#else
> +typedef long long grub_int64_t;
> +#endif
> +
> +typedef unsigned char grub_uint8_t;
> +typedef unsigned short grub_uint16_t;
> +typedef unsigned grub_uint32_t;
> +#if GRUB_CPU_SIZEOF_LONG == 8
> +typedef unsigned long grub_uint64_t;
> +#else
> +typedef unsigned long long grub_uint64_t;
> +#endif
> +
> +/* Misc types.  */
> +#if GRUB_TARGET_SIZEOF_VOID_P == 8
> +typedef grub_uint64_t grub_target_addr_t;
> +typedef grub_uint64_t grub_target_off_t;
> +typedef grub_uint64_t grub_target_size_t;
> +typedef grub_int64_t grub_target_ssize_t;
> +#else
> +typedef grub_uint32_t grub_target_addr_t;
> +typedef grub_uint32_t grub_target_off_t;
> +typedef grub_uint32_t grub_target_size_t;
> +typedef grub_int32_t grub_target_ssize_t;
> +#endif
> +
> +#if GRUB_CPU_SIZEOF_VOID_P == 8
> +typedef grub_uint64_t grub_addr_t;
> +typedef grub_uint64_t grub_size_t;
> +typedef grub_int64_t grub_ssize_t;
> +#else
> +typedef grub_uint32_t grub_addr_t;
> +typedef grub_uint32_t grub_size_t;
> +typedef grub_int32_t grub_ssize_t;
> +#endif
> +
> +#if GRUB_CPU_SIZEOF_VOID_P == 8
> +# define GRUB_ULONG_MAX 18446744073709551615UL
> +# define GRUB_LONG_MAX 9223372036854775807L
> +# define GRUB_LONG_MIN (-9223372036854775807L - 1)
> +#else
> +# define GRUB_ULONG_MAX 4294967295UL
> +# define GRUB_LONG_MAX 2147483647L
> +# define GRUB_LONG_MIN (-2147483647L - 1)
> +#endif
> +
> +#if GRUB_CPU_SIZEOF_VOID_P == 4
> +#define UINT_TO_PTR(x) ((void*)(grub_uint32_t)(x))
> +#define PTR_TO_UINT64(x) ((grub_uint64_t)(grub_uint32_t)(x))
> +#define PTR_TO_UINT32(x) ((grub_uint32_t)(x))
> +#else
> +#define UINT_TO_PTR(x) ((void*)(grub_uint64_t)(x))
> +#define PTR_TO_UINT64(x) ((grub_uint64_t)(x))
> +#define PTR_TO_UINT32(x) ((grub_uint32_t)(grub_uint64_t)(x))
> +#endif
> +
> +/* The type for representing a file offset.  */
> +typedef grub_uint64_t grub_off_t;
> +
> +/* The type for representing a disk block address.  */
> +typedef grub_uint64_t grub_disk_addr_t;
> +
> +/* Byte-orders.  */
> +#define grub_swap_bytes16(x) \
> +({ \
> +   grub_uint16_t _x = (x); \
> +   (grub_uint16_t) ((_x << 8) | (_x >> 8)); \
> +})
> +
> +#if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__
>>= 3) && defined(GRUB_TARGET_I386)
> +static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x)
> +{
> + return __builtin_bswap32(x);
> +}
> +
> +static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
> +{
> + return __builtin_bswap64(x);
> +}
> +#else /* not gcc 4.3 or newer */
> +#define grub_swap_bytes32(x) \
> +({ \
> +   grub_uint32_t _x = (x); \
> +   (grub_uint32_t) ((_x << 24) \
> +                    | ((_x & (grub_uint32_t) 0xFF00UL) << 8) \
> +                    | ((_x & (grub_uint32_t) 0xFF0000UL) >> 8) \
> +                    | (_x >> 24)); \
> +})
> +
> +#define grub_swap_bytes64(x) \
> +({ \
> +   grub_uint64_t _x = (x); \
> +   (grub_uint64_t) ((_x << 56) \
> +                    | ((_x & (grub_uint64_t) 0xFF00ULL) << 40) \
> +                    | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) \
> +                    | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) \
> +                    | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) \
> +                    | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) \
> +                    | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) \
> +                    | (_x >> 56)); \
> +})
> +#endif /* not gcc 4.3 or newer */
> +
> +#ifdef GRUB_CPU_WORDS_BIGENDIAN
> +# define grub_cpu_to_le16(x) grub_swap_bytes16(x)
> +# define grub_cpu_to_le32(x) grub_swap_bytes32(x)
> +# define grub_cpu_to_le64(x) grub_swap_bytes64(x)
> +# define grub_le_to_cpu16(x) grub_swap_bytes16(x)
> +# define grub_le_to_cpu32(x) grub_swap_bytes32(x)
> +# define grub_le_to_cpu64(x) grub_swap_bytes64(x)
> +# define grub_cpu_to_be16(x) ((grub_uint16_t) (x))
> +# define grub_cpu_to_be32(x) ((grub_uint32_t) (x))
> +# define grub_cpu_to_be64(x) ((grub_uint64_t) (x))
> +# define grub_be_to_cpu16(x) ((grub_uint16_t) (x))
> +# define grub_be_to_cpu32(x) ((grub_uint32_t) (x))
> +# define grub_be_to_cpu64(x) ((grub_uint64_t) (x))
> +# ifdef GRUB_TARGET_WORDS_BIGENDIAN
> +#  define grub_target_to_host16(x) ((grub_uint16_t) (x))
> +#  define grub_target_to_host32(x) ((grub_uint32_t) (x))
> +#  define grub_target_to_host64(x) ((grub_uint64_t) (x))
> +#  define grub_host_to_target16(x) ((grub_uint16_t) (x))
> +#  define grub_host_to_target32(x) ((grub_uint32_t) (x))
> +#  define grub_host_to_target64(x) ((grub_uint64_t) (x))
> +# else /* ! GRUB_TARGET_WORDS_BIGENDIAN */
> +#  define grub_target_to_host16(x) grub_swap_bytes16(x)
> +#  define grub_target_to_host32(x) grub_swap_bytes32(x)
> +#  define grub_target_to_host64(x) grub_swap_bytes64(x)
> +#  define grub_host_to_target16(x) grub_swap_bytes16(x)
> +#  define grub_host_to_target32(x) grub_swap_bytes32(x)
> +#  define grub_host_to_target64(x) grub_swap_bytes64(x)
> +# endif
> +#else /* ! WORDS_BIGENDIAN */
> +# define grub_cpu_to_le16(x) ((grub_uint16_t) (x))
> +# define grub_cpu_to_le32(x) ((grub_uint32_t) (x))
> +# define grub_cpu_to_le64(x) ((grub_uint64_t) (x))
> +# define grub_le_to_cpu16(x) ((grub_uint16_t) (x))
> +# define grub_le_to_cpu32(x) ((grub_uint32_t) (x))
> +# define grub_le_to_cpu64(x) ((grub_uint64_t) (x))
> +# define grub_cpu_to_be16(x) grub_swap_bytes16(x)
> +# define grub_cpu_to_be32(x) grub_swap_bytes32(x)
> +# define grub_cpu_to_be64(x) grub_swap_bytes64(x)
> +# define grub_be_to_cpu16(x) grub_swap_bytes16(x)
> +# define grub_be_to_cpu32(x) grub_swap_bytes32(x)
> +# define grub_be_to_cpu64(x) grub_swap_bytes64(x)
> +# ifdef GRUB_TARGET_WORDS_BIGENDIAN
> +#  define grub_target_to_host16(x) grub_swap_bytes16(x)
> +#  define grub_target_to_host32(x) grub_swap_bytes32(x)
> +#  define grub_target_to_host64(x) grub_swap_bytes64(x)
> +#  define grub_host_to_target16(x) grub_swap_bytes16(x)
> +#  define grub_host_to_target32(x) grub_swap_bytes32(x)
> +#  define grub_host_to_target64(x) grub_swap_bytes64(x)
> +# else /* ! GRUB_TARGET_WORDS_BIGENDIAN */
> +#  define grub_target_to_host16(x) ((grub_uint16_t) (x))
> +#  define grub_target_to_host32(x) ((grub_uint32_t) (x))
> +#  define grub_target_to_host64(x) ((grub_uint64_t) (x))
> +#  define grub_host_to_target16(x) ((grub_uint16_t) (x))
> +#  define grub_host_to_target32(x) ((grub_uint32_t) (x))
> +#  define grub_host_to_target64(x) ((grub_uint64_t) (x))
> +# endif
> +#endif /* ! WORDS_BIGENDIAN */
> +
> +#if GRUB_TARGET_SIZEOF_VOID_P == 8
> +#  define grub_host_to_target_addr(x) grub_host_to_target64(x)
> +#else
> +#  define grub_host_to_target_addr(x) grub_host_to_target32(x)
> +#endif
> +
> +
> +
> +
> +
> +
> +
> +#endif /* ! GRUB_TYPES_HEADER */
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-config.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/grub-config.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-config.h 1970-01-01
> 07:00:00.000000000 +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-config.h 2012-12-28
> 16:02:41.006932417 +0800
> @@ -0,0 +1,251 @@
> +/* config.h.  Generated from config.h.in by configure.  */
> +/* config.h.in.  Generated from configure.ac by autoheader.  */
> +
> +/* Define it if GAS requires that absolute indirect calls/jumps are not
> +   prefixed with an asterisk */
> +/* #undef ABSOLUTE_WITHOUT_ASTERISK */
> +
> +/* Define it to \"addr32\" or \"addr32;\" to make GAS happy */
> +#define ADDR32 addr32
> +
> +/* Define it to \"data32\" or \"data32;\" to make GAS happy */
> +#define DATA32 data32
> +
> +/* Define to 1 if translation of program messages to the user's native
> +   language is requested. */
> +#define ENABLE_NLS 1
> +
> +/* Define if C symbols get an underscore after compilation */
> +/* #undef HAVE_ASM_USCORE */
> +
> +/* Define to 1 if you have the `asprintf' function. */
> +#define HAVE_ASPRINTF 1
> +
> +/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
> +   CoreFoundation framework. */
> +/* #undef HAVE_CFLOCALECOPYCURRENT */
> +
> +/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue
> in
> +   the CoreFoundation framework. */
> +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
> +
> +/* Define to 1 if you have the <curses.h> header file. */
> +/* #undef HAVE_CURSES_H */
> +
> +/* Define if the GNU dcgettext() function is already present or
> preinstalled.
> +   */
> +#define HAVE_DCGETTEXT 1
> +
> +/* Define to 1 if you have the <dirent.h> header file, and it defines
> `DIR'.
> +   */
> +#define HAVE_DIRENT_H 1
> +
> +/* Define to 1 if you have the <ft2build.h> header file. */
> +#define HAVE_FT2BUILD_H 1
> +
> +/* Define to 1 if you have the `getgid' function. */
> +#define HAVE_GETGID 1
> +
> +/* Define if getrawpartition() in -lutil can be used */
> +/* #undef HAVE_GETRAWPARTITION */
> +
> +/* Define if the GNU gettext() function is already present or preinstalled.
> */
> +#define HAVE_GETTEXT 1
> +
> +/* Define to 1 if you have the `getuid' function. */
> +#define HAVE_GETUID 1
> +
> +/* Define if you have the iconv() function and it works. */
> +/* #undef HAVE_ICONV */
> +
> +/* Define to 1 if you have the <inttypes.h> header file. */
> +#define HAVE_INTTYPES_H 1
> +
> +/* Define to 1 if you have the <limits.h> header file. */
> +#define HAVE_LIMITS_H 1
> +
> +/* Define to 1 if you have the `lstat' function. */
> +#define HAVE_LSTAT 1
> +
> +/* Define to 1 if you have the <malloc.h> header file. */
> +#define HAVE_MALLOC_H 1
> +
> +/* Define to 1 if you have the `memalign' function. */
> +#define HAVE_MEMALIGN 1
> +
> +/* Define to 1 if you have the `memmove' function. */
> +#define HAVE_MEMMOVE 1
> +
> +/* Define to 1 if you have the <memory.h> header file. */
> +#define HAVE_MEMORY_H 1
> +
> +/* Define to 1 if you have the <ncurses/curses.h> header file. */
> +/* #undef HAVE_NCURSES_CURSES_H */
> +
> +/* Define to 1 if you have the <ncurses.h> header file. */
> +/* #undef HAVE_NCURSES_H */
> +
> +/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'.
> */
> +/* #undef HAVE_NDIR_H */
> +
> +/* Define if opendisk() in -lutil can be used */
> +/* #undef HAVE_OPENDISK */
> +
> +/* Define to 1 if you have the <pci/pci.h> header file. */
> +/* #undef HAVE_PCI_PCI_H */
> +
> +/* Define to 1 if you have the `posix_memalign' function. */
> +#define HAVE_POSIX_MEMALIGN 1
> +
> +/* Define if returns_twice attribute is supported */
> +/* #undef HAVE_RETURNS_TWICE */
> +
> +/* Define to 1 if you have the `sbrk' function. */
> +#define HAVE_SBRK 1
> +
> +/* Define to 1 if you have the <SDL/SDL.h> header file. */
> +/* #undef HAVE_SDL_SDL_H */
> +
> +/* Define to 1 if you have the <stdint.h> header file. */
> +#define HAVE_STDINT_H 1
> +
> +/* Define to 1 if you have the <stdlib.h> header file. */
> +#define HAVE_STDLIB_H 1
> +
> +/* Define to 1 if you have the `strdup' function. */
> +#define HAVE_STRDUP 1
> +
> +/* Define to 1 if you have the <strings.h> header file. */
> +#define HAVE_STRINGS_H 1
> +
> +/* Define to 1 if you have the <string.h> header file. */
> +#define HAVE_STRING_H 1
> +
> +/* Define to 1 if you have the <sys/dir.h> header file, and it defines
> `DIR'.
> +   */
> +/* #undef HAVE_SYS_DIR_H */
> +
> +/* Define to 1 if you have the <sys/fcntl.h> header file. */
> +#define HAVE_SYS_FCNTL_H 1
> +
> +/* Define to 1 if you have the <sys/mkdev.h> header file. */
> +/* #undef HAVE_SYS_MKDEV_H */
> +
> +/* Define to 1 if you have the <sys/ndir.h> header file, and it defines
> `DIR'.
> +   */
> +/* #undef HAVE_SYS_NDIR_H */
> +
> +/* Define to 1 if you have the <sys/stat.h> header file. */
> +#define HAVE_SYS_STAT_H 1
> +
> +/* Define to 1 if you have the <sys/sysmacros.h> header file. */
> +#define HAVE_SYS_SYSMACROS_H 1
> +
> +/* Define to 1 if you have the <sys/types.h> header file. */
> +#define HAVE_SYS_TYPES_H 1
> +
> +/* Define to 1 if you have the <termios.h> header file. */
> +#define HAVE_TERMIOS_H 1
> +
> +/* Define to 1 if you have the <unistd.h> header file. */
> +#define HAVE_UNISTD_H 1
> +
> +/* Define to 1 if you have the <usb.h> header file. */
> +/* #undef HAVE_USB_H */
> +
> +/* Define to 1 if you have the `vasprintf' function. */
> +#define HAVE_VASPRINTF 1
> +
> +/* Define to 1 if `major', `minor', and `makedev' are declared in
> <mkdev.h>.
> +   */
> +/* #undef MAJOR_IN_MKDEV */
> +
> +/* Define to 1 if `major', `minor', and `makedev' are declared in
> +   <sysmacros.h>. */
> +/* #undef MAJOR_IN_SYSMACROS */
> +
> +/* Define to 1 if you enable memory manager debugging. */
> +/* #undef MM_DEBUG */
> +
> +/* Define to 1 if GCC generates calls to __register_frame_info() */
> +/* #undef NEED_REGISTER_FRAME_INFO */
> +
> +/* Name of package */
> +#define PACKAGE "burg"
> +
> +/* Define to the address where bug reports for this package should be sent.
> */
> +#define PACKAGE_BUGREPORT "address@hidden"
> +
> +/* Define to the full name of this package. */
> +#define PACKAGE_NAME "BURG"
> +
> +/* Define to the full name and version of this package. */
> +#define PACKAGE_STRING "BURG 1.98"
> +
> +/* Define to the one symbol short name of this package. */
> +#define PACKAGE_TARNAME "burg"
> +
> +/* Define to the version of this package. */
> +#define PACKAGE_VERSION "1.98"
> +
> +/* The size of `long', as computed by sizeof. */
> +#define SIZEOF_LONG 8
> +
> +/* The size of `void *', as computed by sizeof. */
> +#define SIZEOF_VOID_P 8
> +
> +/* Define to 1 if you have the ANSI C header files. */
> +#define STDC_HEADERS 1
> +
> +/* Version number of package */
> +#define VERSION "1.98"
> +
> +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
> +   significant byte first (like Motorola and SPARC, unlike Intel and VAX).
> */
> +#if defined __BIG_ENDIAN__
> +# define WORDS_BIGENDIAN 1
> +#elif ! defined __LITTLE_ENDIAN__
> +/* # undef WORDS_BIGENDIAN */
> +#endif
> +
> +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
> +   `char[]'. */
> +#define YYTEXT_POINTER 1
> +
> +/* Number of bits in a file offset, on hosts where this is settable. */
> +/* #undef _FILE_OFFSET_BITS */
> +
> +/* Define for large files, on AIX-style hosts. */
> +/* #undef _LARGE_FILES */
> +
> +/* Define to 1 if on MINIX. */
> +/* #undef _MINIX */
> +
> +/* Define to 2 if the system does not provide POSIX.1 features except with
> +   this defined. */
> +/* #undef _POSIX_1_SOURCE */
> +
> +/* Define to 1 if you need to in order for `stat' and other things to work.
> */
> +/* #undef _POSIX_SOURCE */
> +
> +/* Enable extensions on AIX 3, Interix.  */
> +#ifndef _ALL_SOURCE
> +# define _ALL_SOURCE 1
> +#endif
> +/* Enable GNU extensions on systems that have them.  */
> +#ifndef _GNU_SOURCE
> +# define _GNU_SOURCE 1
> +#endif
> +/* Enable threading extensions on Solaris.  */
> +#ifndef _POSIX_PTHREAD_SEMANTICS
> +# define _POSIX_PTHREAD_SEMANTICS 1
> +#endif
> +/* Enable extensions on HP NonStop.  */
> +#ifndef _TANDEM_SOURCE
> +# define _TANDEM_SOURCE 1
> +#endif
> +/* Enable general extensions on Solaris.  */
> +#ifndef __EXTENSIONS__
> +# define __EXTENSIONS__ 1
> +#endif
> +
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub_err.c
> xen-4.1.2-b/tools/ioemu-qemu-xen/grub_err.c
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/grub_err.c 1970-01-01
> 07:00:00.000000000 +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub_err.c 2012-12-28
> 16:02:41.007734164 +0800
> @@ -0,0 +1,186 @@
> +/* err.c - error handling routines */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2002,2005,2007,2008  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "grub_err.h"
> +#include "misc.h"
> +#include <stdarg.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +#define GRUB_MAX_ERRMSG 256
> +#define GRUB_ERROR_STACK_SIZE 10
> +
> +grub_err_t grub_errno;
> +char grub_errmsg[GRUB_MAX_ERRMSG];
> +
> +static struct
> +{
> +  grub_err_t errno;
> +  char errmsg[GRUB_MAX_ERRMSG];
> +} grub_error_stack_items[GRUB_ERROR_STACK_SIZE];
> +
> +static int grub_error_stack_pos;
> +static int grub_error_stack_assert;
> +
> +
> +
> +static int
> +grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap)
> +{
> +  grub_size_t ret;
> +
> +  if (!n)
> +    return 0;
> +
> +
> +  ret = vsnprintf(str, n, fmt, ap);
> +  printf("%s\n", str);
> +  return ret < n ? ret : n;
> +}
> +
> +
> +
> +static int
> +grub_vprintf (const char *fmt, va_list args)
> +{
> +  int ret;
> +
> +  ret = grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), fmt, args);
> +
> +  return ret;
> +}
> +
> +int
> +grub_err_printf (const char *fmt, ...)
> +{
> +  va_list ap;
> +  int ret;
> +
> +  va_start (ap, fmt);
> +  ret = grub_vprintf (fmt, ap);
> +  va_end (ap);
> +
> +  return ret;
> +}
> +
> +
> +grub_err_t
> +grub_error (grub_err_t n, const char *fmt, ...)
> +{
> +  va_list ap;
> +
> +  grub_errno = n;
> +  va_start (ap, fmt);
> +  grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), fmt, ap);
> +  va_end (ap);
> +
> +  return n;
> +}
> +
> +void
> +grub_fatal (const char *fmt, ...)
> +{
> +  va_list ap;
> +
> +  va_start (ap, fmt);
> +  grub_vprintf (_(fmt), ap);
> +  va_end (ap);
> +
> +  exit(1);
> +}
> +
> +void
> +grub_error_push (void)
> +{
> +  /* Only add items to stack, if there is enough room.  */
> +  if (grub_error_stack_pos < GRUB_ERROR_STACK_SIZE)
> +    {
> +      /* Copy active error message to stack.  */
> +      grub_error_stack_items[grub_error_stack_pos].errno = grub_errno;
> +      grub_memcpy (grub_error_stack_items[grub_error_stack_pos].errmsg,
> +                   grub_errmsg,
> +                   sizeof (grub_errmsg));
> +
> +      /* Advance to next error stack position.  */
> +      grub_error_stack_pos++;
> +    }
> +  else
> +    {
> +      /* There is no room for new error message. Discard new error message
> +         and mark error stack assertion flag.  */
> +      grub_error_stack_assert = 1;
> +    }
> +
> +  /* Allow further operation of other components by resetting
> +     active errno to GRUB_ERR_NONE.  */
> +  grub_errno = GRUB_ERR_NONE;
> +}
> +
> +int
> +grub_error_pop (void)
> +{
> +  if (grub_error_stack_pos > 0)
> +    {
> +      /* Pop error message from error stack to current active error.  */
> +      grub_error_stack_pos--;
> +
> +      grub_errno = grub_error_stack_items[grub_error_stack_pos].errno;
> +      grub_memcpy (grub_errmsg,
> +                   grub_error_stack_items[grub_error_stack_pos].errmsg,
> +                   sizeof (grub_errmsg));
> +
> +      return 1;
> +    }
> +  else
> +    {
> +      /* There is no more items on error stack, reset to no error state.
> */
> +      grub_errno = GRUB_ERR_NONE;
> +
> +      return 0;
> +    }
> +}
> +
> +void
> +grub_print_error (void)
> +{
> +  /* Print error messages in reverse order. First print active error
> message
> +     and then empty error stack.  */
> +  do
> +    {
> +      if (grub_errno != GRUB_ERR_NONE)
> +        grub_err_printf ("error: %s.\n", grub_errmsg);
> +    }
> +  while (grub_error_pop ());
> +
> +  /* If there was an assert while using error stack, report about it.  */
> +  if (grub_error_stack_assert)
> +    {
> +      grub_err_printf ("assert: error stack overflow detected!\n");
> +      grub_error_stack_assert = 0;
> +    }
> +}
> +
> +
> +int test_grub_err()
> +{
> +  grub_error(222, "test %s\n", "grub_error");
> +  grub_err_printf("test %s\n", "grub_err_printf");
> +  grub_fatal("test %s\n", "grub_fatal");
> +}
> +
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub_err.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/grub_err.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/grub_err.h 1970-01-01
> 07:00:00.000000000 +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub_err.h 2012-12-28
> 16:02:41.007734164 +0800
> @@ -0,0 +1,81 @@
> +/* err.h - error numbers and prototypes */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2002,2005,2007,2008 Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_ERR_HEADER
> +#define GRUB_ERR_HEADER 1
> +
> +
> +typedef enum
> +  {
> +    GRUB_ERR_NONE = 0,
> +    GRUB_ERR_TEST_FAILURE,
> +    GRUB_ERR_BAD_MODULE,
> +    GRUB_ERR_OUT_OF_MEMORY,
> +    GRUB_ERR_BAD_FILE_TYPE,
> +    GRUB_ERR_FILE_NOT_FOUND,
> +    GRUB_ERR_FILE_READ_ERROR,
> +    GRUB_ERR_BAD_FILENAME,
> +    GRUB_ERR_UNKNOWN_FS,
> +    GRUB_ERR_BAD_FS,
> +    GRUB_ERR_BAD_NUMBER,
> +    GRUB_ERR_OUT_OF_RANGE,
> +    GRUB_ERR_UNKNOWN_DEVICE,
> +    GRUB_ERR_BAD_DEVICE,
> +    GRUB_ERR_READ_ERROR,
> +    GRUB_ERR_WRITE_ERROR,
> +    GRUB_ERR_UNKNOWN_COMMAND,
> +    GRUB_ERR_INVALID_COMMAND,
> +    GRUB_ERR_BAD_ARGUMENT,
> +    GRUB_ERR_BAD_PART_TABLE,
> +    GRUB_ERR_UNKNOWN_OS,
> +    GRUB_ERR_BAD_OS,
> +    GRUB_ERR_NO_KERNEL,
> +    GRUB_ERR_BAD_FONT,
> +    GRUB_ERR_NOT_IMPLEMENTED_YET,
> +    GRUB_ERR_SYMLINK_LOOP,
> +    GRUB_ERR_BAD_GZIP_DATA,
> +    GRUB_ERR_MENU,
> +    GRUB_ERR_TIMEOUT,
> +    GRUB_ERR_IO,
> +    GRUB_ERR_ACCESS_DENIED,
> +    GRUB_ERR_MENU_ESCAPE,
> +    GRUB_ERR_NOT_FOUND,
> +    GRUB_ERR_UNKNOWN
> +
> +  }
> +grub_err_t;
> +
> +
> +#ifndef _
> +# define _(String) String
> +#endif
> +
> +extern grub_err_t grub_errno;
> +extern char grub_errmsg[];
> +
> +grub_err_t grub_error (grub_err_t n, const char *fmt, ...);
> +void grub_fatal (const char *fmt, ...) __attribute__((noreturn));
> +void grub_error_push (void);
> +int grub_error_pop (void);
> +void grub_print_error (void);
> +int grub_err_printf (const char *fmt, ...)
> +     __attribute__ ((format (printf, 1, 2)));
> +int test_grub_err(void);
> +
> +#endif /* ! GRUB_ERR_HEADER */
> diff --exclude=.svn -rpN -U8
> xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/config.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/config.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/config.h 1970-01-01
> 07:00:00.000000000 +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/config.h 2012-12-28
> 16:02:41.008640838 +0800
> @@ -0,0 +1,251 @@
> +/* config.h.  Generated from config.h.in by configure.  */
> +/* config.h.in.  Generated from configure.ac by autoheader.  */
> +
> +/* Define it if GAS requires that absolute indirect calls/jumps are not
> +   prefixed with an asterisk */
> +/* #undef ABSOLUTE_WITHOUT_ASTERISK */
> +
> +/* Define it to \"addr32\" or \"addr32;\" to make GAS happy */
> +#define ADDR32 addr32
> +
> +/* Define it to \"data32\" or \"data32;\" to make GAS happy */
> +#define DATA32 data32
> +
> +/* Define to 1 if translation of program messages to the user's native
> +   language is requested. */
> +#define ENABLE_NLS 1
> +
> +/* Define if C symbols get an underscore after compilation */
> +/* #undef HAVE_ASM_USCORE */
> +
> +/* Define to 1 if you have the `asprintf' function. */
> +#define HAVE_ASPRINTF 1
> +
> +/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
> +   CoreFoundation framework. */
> +/* #undef HAVE_CFLOCALECOPYCURRENT */
> +
> +/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue
> in
> +   the CoreFoundation framework. */
> +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
> +
> +/* Define to 1 if you have the <curses.h> header file. */
> +/* #undef HAVE_CURSES_H */
> +
> +/* Define if the GNU dcgettext() function is already present or
> preinstalled.
> +   */
> +#define HAVE_DCGETTEXT 1
> +
> +/* Define to 1 if you have the <dirent.h> header file, and it defines
> `DIR'.
> +   */
> +#define HAVE_DIRENT_H 1
> +
> +/* Define to 1 if you have the <ft2build.h> header file. */
> +#define HAVE_FT2BUILD_H 1
> +
> +/* Define to 1 if you have the `getgid' function. */
> +#define HAVE_GETGID 1
> +
> +/* Define if getrawpartition() in -lutil can be used */
> +/* #undef HAVE_GETRAWPARTITION */
> +
> +/* Define if the GNU gettext() function is already present or preinstalled.
> */
> +#define HAVE_GETTEXT 1
> +
> +/* Define to 1 if you have the `getuid' function. */
> +#define HAVE_GETUID 1
> +
> +/* Define if you have the iconv() function and it works. */
> +/* #undef HAVE_ICONV */
> +
> +/* Define to 1 if you have the <inttypes.h> header file. */
> +#define HAVE_INTTYPES_H 1
> +
> +/* Define to 1 if you have the <limits.h> header file. */
> +#define HAVE_LIMITS_H 1
> +
> +/* Define to 1 if you have the `lstat' function. */
> +#define HAVE_LSTAT 1
> +
> +/* Define to 1 if you have the <malloc.h> header file. */
> +#define HAVE_MALLOC_H 1
> +
> +/* Define to 1 if you have the `memalign' function. */
> +#define HAVE_MEMALIGN 1
> +
> +/* Define to 1 if you have the `memmove' function. */
> +#define HAVE_MEMMOVE 1
> +
> +/* Define to 1 if you have the <memory.h> header file. */
> +#define HAVE_MEMORY_H 1
> +
> +/* Define to 1 if you have the <ncurses/curses.h> header file. */
> +/* #undef HAVE_NCURSES_CURSES_H */
> +
> +/* Define to 1 if you have the <ncurses.h> header file. */
> +/* #undef HAVE_NCURSES_H */
> +
> +/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'.
> */
> +/* #undef HAVE_NDIR_H */
> +
> +/* Define if opendisk() in -lutil can be used */
> +/* #undef HAVE_OPENDISK */
> +
> +/* Define to 1 if you have the <pci/pci.h> header file. */
> +/* #undef HAVE_PCI_PCI_H */
> +
> +/* Define to 1 if you have the `posix_memalign' function. */
> +#define HAVE_POSIX_MEMALIGN 1
> +
> +/* Define if returns_twice attribute is supported */
> +/* #undef HAVE_RETURNS_TWICE */
> +
> +/* Define to 1 if you have the `sbrk' function. */
> +#define HAVE_SBRK 1
> +
> +/* Define to 1 if you have the <SDL/SDL.h> header file. */
> +/* #undef HAVE_SDL_SDL_H */
> +
> +/* Define to 1 if you have the <stdint.h> header file. */
> +#define HAVE_STDINT_H 1
> +
> +/* Define to 1 if you have the <stdlib.h> header file. */
> +#define HAVE_STDLIB_H 1
> +
> +/* Define to 1 if you have the `strdup' function. */
> +#define HAVE_STRDUP 1
> +
> +/* Define to 1 if you have the <strings.h> header file. */
> +#define HAVE_STRINGS_H 1
> +
> +/* Define to 1 if you have the <string.h> header file. */
> +#define HAVE_STRING_H 1
> +
> +/* Define to 1 if you have the <sys/dir.h> header file, and it defines
> `DIR'.
> +   */
> +/* #undef HAVE_SYS_DIR_H */
> +
> +/* Define to 1 if you have the <sys/fcntl.h> header file. */
> +#define HAVE_SYS_FCNTL_H 1
> +
> +/* Define to 1 if you have the <sys/mkdev.h> header file. */
> +/* #undef HAVE_SYS_MKDEV_H */
> +
> +/* Define to 1 if you have the <sys/ndir.h> header file, and it defines
> `DIR'.
> +   */
> +/* #undef HAVE_SYS_NDIR_H */
> +
> +/* Define to 1 if you have the <sys/stat.h> header file. */
> +#define HAVE_SYS_STAT_H 1
> +
> +/* Define to 1 if you have the <sys/sysmacros.h> header file. */
> +#define HAVE_SYS_SYSMACROS_H 1
> +
> +/* Define to 1 if you have the <sys/types.h> header file. */
> +#define HAVE_SYS_TYPES_H 1
> +
> +/* Define to 1 if you have the <termios.h> header file. */
> +#define HAVE_TERMIOS_H 1
> +
> +/* Define to 1 if you have the <unistd.h> header file. */
> +#define HAVE_UNISTD_H 1
> +
> +/* Define to 1 if you have the <usb.h> header file. */
> +/* #undef HAVE_USB_H */
> +
> +/* Define to 1 if you have the `vasprintf' function. */
> +#define HAVE_VASPRINTF 1
> +
> +/* Define to 1 if `major', `minor', and `makedev' are declared in
> <mkdev.h>.
> +   */
> +/* #undef MAJOR_IN_MKDEV */
> +
> +/* Define to 1 if `major', `minor', and `makedev' are declared in
> +   <sysmacros.h>. */
> +/* #undef MAJOR_IN_SYSMACROS */
> +
> +/* Define to 1 if you enable memory manager debugging. */
> +/* #undef MM_DEBUG */
> +
> +/* Define to 1 if GCC generates calls to __register_frame_info() */
> +/* #undef NEED_REGISTER_FRAME_INFO */
> +
> +/* Name of package */
> +#define PACKAGE "burg"
> +
> +/* Define to the address where bug reports for this package should be sent.
> */
> +#define PACKAGE_BUGREPORT "address@hidden"
> +
> +/* Define to the full name of this package. */
> +#define PACKAGE_NAME "BURG"
> +
> +/* Define to the full name and version of this package. */
> +#define PACKAGE_STRING "BURG 1.98"
> +
> +/* Define to the one symbol short name of this package. */
> +#define PACKAGE_TARNAME "burg"
> +
> +/* Define to the version of this package. */
> +#define PACKAGE_VERSION "1.98"
> +
> +/* The size of `long', as computed by sizeof. */
> +#define SIZEOF_LONG 8
> +
> +/* The size of `void *', as computed by sizeof. */
> +#define SIZEOF_VOID_P 8
> +
> +/* Define to 1 if you have the ANSI C header files. */
> +#define STDC_HEADERS 1
> +
> +/* Version number of package */
> +#define VERSION "1.98"
> +
> +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
> +   significant byte first (like Motorola and SPARC, unlike Intel and VAX).
> */
> +#if defined __BIG_ENDIAN__
> +# define WORDS_BIGENDIAN 1
> +#elif ! defined __LITTLE_ENDIAN__
> +/* # undef WORDS_BIGENDIAN */
> +#endif
> +
> +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
> +   `char[]'. */
> +#define YYTEXT_POINTER 1
> +
> +/* Number of bits in a file offset, on hosts where this is settable. */
> +/* #undef _FILE_OFFSET_BITS */
> +
> +/* Define for large files, on AIX-style hosts. */
> +/* #undef _LARGE_FILES */
> +
> +/* Define to 1 if on MINIX. */
> +/* #undef _MINIX */
> +
> +/* Define to 2 if the system does not provide POSIX.1 features except with
> +   this defined. */
> +/* #undef _POSIX_1_SOURCE */
> +
> +/* Define to 1 if you need to in order for `stat' and other things to work.
> */
> +/* #undef _POSIX_SOURCE */
> +
> +/* Enable extensions on AIX 3, Interix.  */
> +#ifndef _ALL_SOURCE
> +# define _ALL_SOURCE 1
> +#endif
> +/* Enable GNU extensions on systems that have them.  */
> +#ifndef _GNU_SOURCE
> +# define _GNU_SOURCE 1
> +#endif
> +/* Enable threading extensions on Solaris.  */
> +#ifndef _POSIX_PTHREAD_SEMANTICS
> +# define _POSIX_PTHREAD_SEMANTICS 1
> +#endif
> +/* Enable extensions on HP NonStop.  */
> +#ifndef _TANDEM_SOURCE
> +# define _TANDEM_SOURCE 1
> +#endif
> +/* Enable general extensions on Solaris.  */
> +#ifndef __EXTENSIONS__
> +# define __EXTENSIONS__ 1
> +#endif
> +
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/fat.c
> xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/fat.c
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/grub-fat/fat.c 1970-01-01
> 07:00:00.000000000 +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/grub-fat/fat.c 2012-12-28
> 16:02:41.008640838 +0800
> @@ -0,0 +1,711 @@
> +/* fat.c - FAT filesystem */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009  Free
> Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include "misc.h"
> +#include "fat.h"
> +
> +
> +static int
> +fat_log2 (unsigned x)
> +{
> +  int i;
> +
> +  if (x == 0)
> +    return -1;
> +
> +  for (i = 0; (x & 1) == 0; i++)
> +    x >>= 1;
> +
> +  if (x != 1)
> +    return -1;
> +
> +  return i;
> +}
> +
> +
> +struct grub_fat_data *
> +grub_fat_mount (BlockDriverState *bs, uint32_t part_off_sector)
> +{
> +  struct grub_fat_bpb bpb;
> +  struct grub_fat_data *data = 0;
> +  grub_uint32_t first_fat, magic;
> +  int64_t off_bytes = (int64_t)part_off_sector << GRUB_DISK_SECTOR_BITS;
> +
> +  if (! bs)
> +    goto fail;
> +
> +  data = (struct 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->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 = 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 > $@
> +
> +info: qemu-doc.info qemu-tech.info
> +
> +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 = diro->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 = 0;
> +  grub_off_t off_bytes = (grub_off_t)part_off_sector << BLK_SHR;
> +
> +  if (!bs)
> +    goto fail;
> +
> +  data = (struct 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;
> +  data->cmft.data = 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 = node->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 = 0;
> +  struct grub_fshelp_node *fdiro = 0;
> +  struct grub_ntfs_dir_closure c = {0};
> +
> +  data = grub_ntfs_mount (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 = 0;
> +  struct grub_fshelp_node *mft = 0;
> +
> +
> +  data = grub_ntfs_mount (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 = 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 = file->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 = NULL;
> +
> +        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 = NULL;
> +
> +        char* p = strchr(filename, '/');
> +        if(!p)
> +        {
> +            errx(-1, "please check the file path!\n");
> +        }
> +        else
> +        {
> +            p = strchr(p, '/');
> +            if(!p) errx(-1, "check the file path!!\n");
> +        }
> +
> +        get_partition_path(filename, &which_part, &path);
> +        DBG("part=%d, path=%s", which_part, path);
> +        if(which_part < 1 || which_part > count)
> +        {
> +            printf("error: check the partition number!\n");
> +            goto fail;
> +        }
> +        file->part_off_sector = parts[which_part -
> 1].part.start_sector_abs;
> +        judge_fs(&parts[which_part - 1]);
> +        FS_TYPE fs_type = parts[which_part - 1].fs_type;
> +        (fs_type == FS_UNKNOWN) ? errx(1, "unknown file system!\n") : 0;
> +        grub_fs_t grub_fs_plg = grub_fs_plug[fs_type];
> +
> +        if(grub_fs_plg.open(file, path) == 0)
> +        {
> +            //printf("file size=%zd bytes\n", (file->size));
> +
> +            grub_size_t len = file->size;
> +            grub_off_t off = 0;
> +            char  tmpfile[256]={};
> +            strncpy(tmpfile, getenv("HOME"), sizeof(tmpfile));
> +            tmpfile[sizeof(tmpfile) - 1] = '\0';
> +            strcat(tmpfile, "/tmp.file");
> +
> +            if(!buf)
> +            {
> +                perror("not enough memory!\n");
> +                goto fail;
> +            }
> +            else
> +            {
> +                grub_size_t readed = 0;
> +                grub_size_t left  = len;
> +                grub_size_t total = 0;
> +                FILE* f = fopen(tmpfile ,"w");
> +                if(!f)
> +                {
> +                    perror("fopen error");
> +                    goto fail;
> +                }
> +
> +
> +                (left > buf_size) ? (left = buf_size) : 0;
> +                while((readed = grub_fs_plg.read(file, off, left, buf))
> +                      && total <= len
> +                      && readed > 0)
> +                {
> +                    DBG("readed=%zd", readed);
> +                    total += fwrite(buf, 1, readed, f);
> +                    off = total;
> +                    left = len - total;
> +                    (left <= buf_size) ? 0  : (left = buf_size);
> +                    DBG("total=%zd", total);
> +                };
> +                fclose(f);
> +
> +                if(total != len)
> +                {
> +                    perror("read error");
> +                    goto fail;
> +                }
> +                else
> +                {
> +                    sprintf(buf, "cat %s", tmpfile);
> +                    system(buf);
> +
> +                }
> +            }
> +        }
> +        else
> +        {
> +            printf("open failed!\n");
> +        }
> +
> +
> +        grub_fs_plg.close(file);
> +        free(file);
> +    }
> +
> +
> +  fail:
> +    free(buf);
> +    bdrv_delete(bs);
> +    free(parts);
> +    return 0;
> +}
> +
> +
> +
>  static int img_create(int argc, char **argv)
>  {
>      int c, ret, flags;
>      const char *fmt = "raw";
>      const char *filename;
>      const char *base_filename = NULL;
>      uint64_t size;
>      const char *p;
> @@ -850,16 +1191,17 @@ static void img_snapshot(int argc, char
>      }
>
>      /* Cleanup */
>      bdrv_delete(bs);
>  }
>
>  int main(int argc, char **argv)
>  {
> +
>      const char *cmd;
>
>      bdrv_init();
>      if (argc < 2)
>          help();
>      cmd = argv[1];
>      argc--; argv++;
>      if (!strcmp(cmd, "create")) {
> @@ -867,13 +1209,19 @@ int main(int argc, char **argv)
>      } else if (!strcmp(cmd, "commit")) {
>          img_commit(argc, argv);
>      } else if (!strcmp(cmd, "convert")) {
>          img_convert(argc, argv);
>      } else if (!strcmp(cmd, "info")) {
>          img_info(argc, argv);
>      } else if (!strcmp(cmd, "snapshot")) {
>          img_snapshot(argc, argv);
> -    } else {
> +    } else if (!strcmp(cmd, "ls")) {
> +        img_ls(argc, argv);
> +    } else if (!strcmp(cmd, "cat")) {
> +        img_cat(argc, argv);
> +    }
> +    else {
>          help();
>      }
> +
>      return 0;
>  }
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/types.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/types.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/types.h 1970-01-01 07:00:00.000000000
> +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/types.h 2012-12-28 16:02:41.016932622
> +0800
> @@ -0,0 +1,35 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2002,2006,2007  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_TYPES_CPU_HEADER
> +#define GRUB_TYPES_CPU_HEADER 1
> +
> +/* The size of void *.  */
> +#define GRUB_TARGET_SIZEOF_VOID_P 4
> +
> +/* The size of long.  */
> +#define GRUB_TARGET_SIZEOF_LONG 4
> +
> +/* i386 is little-endian.  */
> +#undef GRUB_TARGET_WORDS_BIGENDIAN
> +
> +#define GRUB_TARGET_I386 1
> +
> +#define GRUB_TARGET_MIN_ALIGN 1
> +
> +#endif /* ! GRUB_TYPES_CPU_HEADER */
> diff --exclude=.svn -rpN -U8 xen-4.1.2-a/tools/ioemu-qemu-xen/x86_64/types.h
> xen-4.1.2-b/tools/ioemu-qemu-xen/x86_64/types.h
> --- xen-4.1.2-a/tools/ioemu-qemu-xen/x86_64/types.h 1970-01-01
> 07:00:00.000000000 +0700
> +++ xen-4.1.2-b/tools/ioemu-qemu-xen/x86_64/types.h 2012-12-28
> 16:02:41.017802371 +0800
> @@ -0,0 +1,39 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2008  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_TYPES_CPU_HEADER
> +#define GRUB_TYPES_CPU_HEADER 1
> +
> +/* The size of void *.  */
> +#define GRUB_TARGET_SIZEOF_VOID_P 8
> +
> +/* The size of long.  */
> +#ifdef __MINGW32__
> +#define GRUB_TARGET_SIZEOF_LONG 4
> +#else
> +#define GRUB_TARGET_SIZEOF_LONG 8
> +#endif
> +
> +/* x86_64 is little-endian.  */
> +#undef GRUB_TARGET_WORDS_BIGENDIAN
> +
> +#define GRUB_TARGET_X86_64 1
> +
> +#define GRUB_TARGET_MIN_ALIGN 1
> +
> +#endif /* ! GRUB_TYPES_CPU_HEADER */
>
>



reply via email to

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