免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1476 | 回复: 0

OpenBSD源代码阅读/sbin/mbr.c [复制链接]

论坛徽章:
0
发表于 2007-02-03 17:20 |显示全部楼层

                               
               
               
                /*    $OpenBSD: mbr.c,v 1.22 2006/05/29 05:09:36 ray Exp $    */
/*
* Copyright (c) 1997 Tobias Weingartner
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include err.h>
#include errno.h>
#include util.h>
#include stdio.h>
#include unistd.h>
#include memory.h>
#include sys/fcntl.h>
#include sys/ioctl.h>
#include sys/types.h>
#include sys/stat.h>
#include sys/disklabel.h>
#include sys/dkio.h>
#include machine/param.h>
#include "disk.h"
#include "misc.h"
#include "mbr.h"
#include "part.h"
mbr_t结构定义在mbr.h中,如下:
typedef struct _mbr_t {
    off_t reloffset;
    off_t offset;
    unsigned char code[MBR_CODE_SIZE]; mbr的代码
    prt_t part[NDOSPART]; 磁盘分区表的结构
NDOSPART=4,定义在src/sys/arch/i386/include/disklabe.h中
prt_t 为分区表的结构,定义在part.h中,如下:
/* Partition type */typedef struct _prt_t {    u_int32_t shead, scyl, ssect; 开始的磁头号shead,柱面scyl,扇区ssect    u_int32_t ehead, ecyl, esect; 结束的磁头号shead,柱面scyl,扇区ssect    u_int32_t bs; 由shead, scyl, ssect计算的开始扇区,begin sector的缩写    u_int32_t ns; 分区占用的扇区的数量,number sector的缩写    unsigned char flag; 是否是活动分区的标志    unsigned char id; 分区的类型的ID编号} prt_t;
    unsigned short signature; 是否是启动盘的标志,如果是则填写0x55AA
} mbr_t;
disk_t定义在disk.h中,结构如下
typedef struct _DISK_metrics {
    u_int32_t cylinders; 柱面数
    u_int32_t heads;      磁头数
    u_int32_t sectors;    扇区数
    u_int32_t size;        磁盘大小
} DISK_metrics;
typedef struct _disk_t {
    char *name;                磁盘名字
    DISK_metrics *bios;
    DISK_metrics *label;
    DISK_metrics *real; 实际的磁盘柱面,磁头,扇区信息
} disk_t;
/*MBR_init这个函数用于填写mbr这个数据结构 */
void  MBR_init(disk_t *disk, mbr_t *mbr)
{
    /* Fix up given mbr for this disk */
    mbr->part[0].flag = 0;
    mbr->part[1].flag = 0;
    mbr->part[2].flag = 0;分区0, 1, 2都设置为非活动的
   
    mbr->part[3].flag = DOSACTIVE; 分区3设置为活动分区
    mbr->signature = DOSMBR_SIGNATURE; 启动盘标志
在src/sys/arch/i386/include/disklabe.h中
#define DOSACTIVE (0x80)
#define DOSMBR_SIGNATURE  (0xaa55)
#define DOSPTYPE_OPENBSD    0xa6 /* openbsd 分区类型 */
    /* Use whole disk, save for first head, on first cyl. */
    mbr->part[3].id = DOSPTYP_OPENBSD; 初始化分区3为OpenBSD的分区
    mbr->part[3].scyl = 0; start cylinder 开始柱面号
    mbr->part[3].shead = 1;start header 开始磁头号
    mbr->part[3].ssect = 1;start sector 开始扇区号
    从上面的代码可以看出,OpenBSD的分区放在0柱面,1磁头,1扇区开始的地方
    /* Go right to the end */
    mbr->part[3].ecyl = disk->real->cylinders - 1; 结束柱面号
    mbr->part[3].ehead = disk->real->heads - 1; 结束磁头号
    mbr->part[3].esect = disk->real->sectors; 结束扇区号
    /* Fix up start/length fields */
    PRT_fix_BN(disk, &mbr->part[3], 3); 修正分析3的分区表信息,这个函数
是在part.c中实现的,在继续分析下面的代码之前,让我们看看这个函数都干了什么?
/* PRT_fix_BN 参数说明如下:
    disk_t* disk:  磁盘
    part* part:   分区
    int pn: 分区号
*/
void PRT_fix_BN(disk_t *disk, prt_t *part, int pn)
{    u_int32_t spt, tpc, spc;
    u_int32_t start = 0;    u_int32_t end = 0;
    ___________________________________________________
    |                        变量说明                   |
    |spt: sector per track 每个磁道的扇区数                  |
    |tpc: track per cylinder 每个柱面的磁道数                 |
    |spc: sector per cylinder 每个柱面的扇区数               |
    |start: 分区开始的扇区编号                                    |
    |end:分区结束的扇区编号                                         |
    |__________________________________________________|    /* Zero out entry if not used */    if (part->id == DOSPTYP_UNUSED ) {        memset(part, 0, sizeof(*part));        return;    }    /* Disk metrics */    spt = disk->real->sectors;  /*每个磁道的扇区数 */    tpc = disk->real->heads;    /*每个柱面的磁道数 */    spc = spt * tpc;                /*每个柱面的扇区数 */    start += part->scyl * spc;    /*part->scyl--->分区的开始柱面号 */    start += part->shead * spt;   /*part->shead--->分区的开始磁头号 */    start += part->ssect - 1;   /*part->ssect--->分区的开始扇区号 */        end += part->ecyl * spc;    end += part->ehead * spt;    end += part->esect - 1;   /*上面计算出了分区从哪个扇区开始,到哪里结束 */
    /* XXX - Should handle this... */    if (start > end)        warn("Start of partition #%d after end!", pn);    part->bs = start; /*设置分区开始位置 */    part->ns = (end - start) + 1; /*设置分区扇区数量 */}从上面可以看出,PRT_fix_BN这个函数只是计算出分区的开始扇区和占用扇区数量。
#if defined(__powerpc__) || defined(__mips__)
    /* Now fix up for the MS-DOS boot partition on PowerPC. */
    对于x86CPU来说,可以不用看下面的这段修正代码
    mbr->part[0].flag = DOSACTIVE;    /* Boot from dos part */
    mbr->part[3].flag = 0;
    mbr->part[3].ns += mbr->part[3].bs;
    mbr->part[3].bs = mbr->part[0].bs + mbr->part[0].ns;
    mbr->part[3].ns -= mbr->part[3].bs;
    PRT_fix_CHS(disk, &mbr->part[3]);
    if ((mbr->part[3].shead != 1) || (mbr->part[3].ssect != 1)) {
        /* align the partition on a cylinder boundary */
        mbr->part[3].shead = 0;
        mbr->part[3].ssect = 1;
        mbr->part[3].scyl += 1;
    }
    /* Fix up start/length fields */
    PRT_fix_BN(disk, &mbr->part[3], 3);
#endif
}
               
                MBR_parse这个函数分析主引导记录
参数:disk_t* disk: 代表磁盘
     char* mbr_buf:
     off_t offset:
     off_t reloff:
     mbr_t* mbr:
void
MBR_parse(disk_t *disk, char *mbr_buf, off_t offset, off_t reloff, mbr_t *mbr)
{
    int i;
    memcpy(mbr->code, mbr_buf, MBR_CODE_SIZE);
    mbr->offset = offset;
    mbr->reloffset = reloff;
    mbr->signature = getshort(&mbr_buf[MBR_SIG_OFF]);
    for (i = 0; i  NDOSPART; i++)
        PRT_parse(disk, &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i],
            offset, reloff, &mbr->part);
}
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/31277/showart_242394.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP