ISO9660文件系统分析

需要了解ISO9660文件系统的规范。

总体情况


首先我们先要有一个mkisofs这样的制作iso文件的工具,用它来制作一个iso文件,里面放上几个非空文件(至于为什么非空,最后会有介绍)

然后再有一个hexdump这样二进制文件查看器

先来看一下这个表格

先看第一行,说的是前 32768个字节被保留,十进制不好表示,换成十六进制就是0x8000
照此我们先用hexdump看一下我的mkisofs生成的iso文件

hexdump -C os.iso | less

正好符合,前0x8000字节都是0,不过貌似这是未使用而不是保留,所以如果你的工具往里面写点什么也应该可以
向下看是Data Area,先看第一个部分Volume Descriptor

Volume Descriptor

这是一个 Volume Descriptor的基本模板
第一个字节是Type,来看一下取值范围

255(0xff)表示这是最后一个Volume Descriptor,4-254都是保留,剩下的我们只打算看 Primary Volume Descriptor,其他的都无视掉
接下来是Identifier,五个字节,总是"CD001",我们写程序读取的时候就可以判断,不是就说明出错了

然后版本,一个字节,无视掉

剩下的就是最重要的数据区了,对于不同的Type有不同的数据,Volume Descriptor Set Terminator只是一个标记,它没有数据

所以我们就很清楚了,我们只用看一下Primary Volume Descriptor的数据区就好了

Primary Volume Descriptor
这个表格非常长,很多我们都用不到,我们只用到一个信息,我们也只贴出这一个


偏移是156,长度是34(0x22),根目录的入口,这是一个什么格式呢?这就是我们今天新出现的最后一个,也是最重要的一个格式
Directories

这个结构既可以代表目录,也可以代表文件
鉴于我们现在的这个结构来自Volume Descriptor中的,它代表ROOT目录,所以我们就不用判断Flags而直接认定就是文件夹了

看一下hexdump的输出:

开始地址是第一行的22那个地方,表明有0x22个字节,正好34个,与我们之前的描述相符
看一下"File identifier",就是这个文件的名称,这里是"/",前一个字节表示长度

然后再看一下"Location of extent (LBA) in both-endian format",有8个字节,前四个字节是小端的LBA号,后四个字节是大端的LBA号。注意:LBA号(逻辑扇区号)。

因为我们后面要用C语言读取,所以当然考虑小端而不是大端,尽管大端更符合人类思维.....

这里是18 00 00 00 00 00 00 18,表明LBA号是18

对于目录,这里指向的LBA里储存的数据是一个这个结构的数组,对于文件,当然储存的是文件内容了
计算一下偏移 24 * 2048 = 0x18 * 0x800 = 0xc000

再看一下:

第一个的大小是0x90,它的LBA指向是0x18,我没有仔细研究过这种指向的LBA反而小于等于自身LBA的这种结构
猜测可能是类似"/""."".."之类的"目录",由于我们并不需要把这些打印出来,而且打印如果不加判断可能会无限递归,我们先将其略过

说了这是一个数组,所以直接找到偏移0x90 + 0x00处的地方,发现指向的LBA仍然是0x18,继续略过,几次之后找到了一个文件

起始地址是第一行的84那里,然后往下找,找到"1b 00 00 00 00 00 00 1b",这就是刚刚的"回文"LBA号
由于这是一个文件,说明这个文件内容的LBA号就是0x1b

"00 02 00 00 00 00 02 00"是"回文"的大小,表明这个文件大小是0x200,就是512个字节

然后第三行倒数第二个字节,0a表示的是这个文件名的长度

往后的0a个字节都是这个文件名 "BOOT.BIN;1"

(ISO储存文件会自动把文件后面加上;1,并且小写转换成大写,这部分我们要自己处理,文件夹不会加上;1)

遍历所有文件并打印


接下来我们就要把以上讨论的问题转化为代码了,先来看第一部分,寻找Primary Volume Descriptor

static int parseISO9660FileSystem(IDEDevice *device)
{
   /*See also http://wiki.osdev.org/ISO_9660.*/
   /*And http://en.wikipedia.org/wiki/ISO_9660.*/
   u8  *buf8  = (u8  *)ideIOBuffer;
 
   /*System Area (32,768 B)     Unused by ISO 9660*/
   /*32786 = 0x8000.*/
   u64 lba = (0x8000 / 0x800); /*从0x8000的地方开始寻找.*/
 
   for(;;++lba)
   {
      if(ideRead(device,lba,ATAPI_SECTOR_SIZE,buf8)) 
         return -1; /*It may not be inserted if error.*/
      /*Identifier is always "CD001".*/
      if(buf8[1] != 'C' ||
         buf8[2] != 'D' ||
         buf8[3] != '0' ||
         buf8[4] != '0' ||
         buf8[5] != '1' ) /*判断CD001 不符合直接返回.*/
         return -1;
       if(buf8[0] == 0xff) /*Volume Descriptor Set Terminator.*/
         return -1; /*如果这是最后一个 也返回.*/
       if(buf8[0] != 0x01 /*Primary Volume Descriptor.*/)
         continue; /*不是Primary Volume Descriptor就继续*/
       
       /*Directory entry for the root directory.*/
       if(buf8[156] != 0x22 /*Msut 34.*/)
          return -1; /*看前边,这里必须是34个字节.*/
 
       /*Location of extent (LBA) in both-endian format.*/
       lba = *(u32 *)(buf8 + 156 + 2);
       break; /*读LBA,跳出.*/
   }
   
   return parseISO9660FileSystemDir(device,lba,buf8,0);     /*分析ROOT目录里的文件.*/
}


再来看一下parseISO9660FileSystemDir,这是一个简单的递归函数

static int parseISO9660FileSystemDir(
   IDEDevice *device,u64 lba,u8 *buf8,int depth)
{
   u64 offset = 0; /*要读的文件(夹)的信息结构的偏移.*/
   u8 isDir = 0; /*是否是文件夹.*/
   u8 needRead = 0; /*需不需要重新读.*/
   if(ideRead(device,lba,ATAPI_SECTOR_SIZE,buf8))
      return -1; /*读取失败直接返回.*/
   for(;;offset += buf8[offset + 0x0] /*Length of Directory Record.*/)
   {
      while(offset >= ATAPI_SECTOR_SIZE)
      {
         offset -= ATAPI_SECTOR_SIZE;
         ++lba;
         needRead = 1;
         /*Read again.*/
      } /*偏移超出这个扇区的范围就修正一下.*/
      if(needRead)
         if(ideRead(device,lba,ATAPI_SECTOR_SIZE,buf8))
            return -1; /*如果修正了就再读一次.*/
      needRead = 0;
      
      if(buf8[offset + 0x0] == 0x0) /*No more.*/
         break; /*大小是0说明结束了,退出.*/
       
      /*Location of extent (LBA) in both-endian format.*/
      u64 fileLBA = *(u32 *)(buf8 + offset + 0x2);
      if(fileLBA <= lba) 
        continue; /*获取文件LBA,小于就继续吧.*/
      int __depth = depth;
      while(__depth--)
         printk("--"); /*形成一个视觉效果.*/
 
      isDir = buf8[offset + 25] & 0x2; /*Is it a dir?*/
 
      u64 filesize = *(u32 *)(buf8 + offset + 10);
 
      /*Length of file identifier (file name). 
       * This terminates with a ';' character 
       * followed by the file ID number in ASCII coded decimal ('1').*/
      u64 filenameLength = buf8[offset + 32];
      if(!isDir) /*如果是文件就要删掉最后的";1".*/
         filenameLength -= 2; /*Remove ';' and '1'.*/
 
      char filename[filenameLength + 1]; /*Add 1 for '\0'.*/
      memcpy((void *)filename,
         (const void *)(buf8 + offset + 33),
         filenameLength); /*把文件名复制过来.*/
 
      if((!isDir) && (filename[0] == '_'))
         filename[0] = '.'; 
      if((!isDir) && (filename[filenameLength - 1] == '.'))
         filename[filenameLength - 1] = '\0';
      else
         filename[filenameLength] = '\0'; /*做一些修正.*/
 
      /*To lower.*/
      for(u64 i = 0;i < filenameLength;++i)
         if((filename[i] <= 'Z') && (filename[i] >= 'A'))
            filename[i] -= 'A' - 'a'; /*全部转换成小写(好看一点).*/
      if(isDir)
      {
         printk("LBA:%d.",(int)fileLBA);
         printk("Dirname:%s\n",filename); /*打印出目录信息.*/
         parseISO9660FileSystemDir(device,fileLBA,buf8,depth + 1); /*递归.*/
         ideRead(device,lba,ATAPI_SECTOR_SIZE,buf8); /*上一个递归修改了buf8,重新读.*/
         /*We must read again.*/
      }
      else
      {
         if(filesize != 0)
            printk("LBA:%d.",(int)fileLBA);
         else
            printk("Null file,no LBA."); /*如果这个文件是空的,LBA地址无效.*/
   /*这也就是刚开始时为什么要用非空文件的原因,空文件看不到正确的LBA地址.*/
            /*LBA may not be right if this file is null!*/
         printk("Filename:%s\n",filename);
      }
   }
 
 
   return 0; /*返回......*/
}

参考资料
ISO9660 维基百科:http://en.wikipedia.org/wiki/ISO_9660

ISO9660 OSDEV百科:http://wiki.osdev.org/ISO_9660

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ISO 26262是一套针对汽车电子系统的安全标准,旨在确保汽车在设计、开发、生产和操作过程中的安全性。该标准包含一系列的体系文件,以指导汽车制造商、供应商和开发人员在设计和开发安全相关电子系统时遵循的流程和方法。这些文件包括: 1. ISO 26262-1:引言和术语。此文件为ISO 26262提供了总体引言和定义词汇表,确保在整个标准中使用一致的术语。 2. ISO 26262-2:管理过程。此文件描述了开发安全相关电子系统时需要实施的管理过程,包括项目管理、辨识风险、安全需求分析和发布管理等。 3. ISO 26262-3:概念阶段。此文件指导在概念阶段执行的活动,包括系统级安全概念的开发、安全目标的定义和安全需求的分析等。 4. ISO 26262-4:产品开发阶段。此文件详细描述了在产品开发阶段的活动和要求,包括硬件和软件开发过程、安全文档的编制和安全验证等。 5. ISO 26262-5:产品生产和操作阶段。此文件提供了在产品生产和操作阶段需要遵循的指南,包括生产过程的安全要求、故障诊断和故障处理等。 6. ISO 26262-6:适配性。此文件讨论了特定应用领域或技术本身无法涵盖的情况下的适配性问题,以保证标准的灵活应用。 7. ISO 26262-7:支持文件。此文件包含了ISO 26262所需的支持文件,例如安全目录、模板和示例等。 这些文件为汽车行业提供了一套全面的安全指南,以确保安全相关电子系统的设计和开发符合国际标准。它们为汽车制造商和供应商提供了必要的方向和方法,以确保车辆的安全性和可靠性,以保护乘客和其他路上的交通参与者的生命和财产安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值