- 论坛徽章:
- 0
|
/* $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 |
|