⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 partscan.c

📁 freedos32的源代码
💻 C
字号:
/************************************************************************** * FreeDOS 32 BIOSDisk Driver                                             * * Disk drive support via BIOS                                            * * by Salvo Isaja                                                         * *                                                                        * * Copyright (C) 2001-2003, Salvatore Isaja                               * *                                                                        * * This is "partscan.c" - Hard disk partitions scanner                    * *                                                                        * *                                                                        * * This file is part of the FreeDOS32 BIOSDisk Driver.                    * *                                                                        * * The FreeDOS32 BIOSDisk Driver 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 2 of the  * * License, or (at your option) any later version.                        * *                                                                        * * The FreeDOS32 BIOSDisk Driver 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 the FreeDOS32 BIOSDisk Driver; see the file COPYING;        * * if not, write to the Free Software Foundation, Inc.,                   * * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                * **************************************************************************//* Modifications (#define directives below) by Nils Labugt, Mach 2005 *//* to make this file compile with the ATA driver  */#define FD32DEV#define SHOWMSG#ifdef __BIOSDISK__#include <errno.h>#include "biosdisk.h"#define PS_DEVICE Disk#define PS_READ biosdisk_read#define PS_HEADS bios_h#define PS_SECTS bios_s#define PS_BLOCK_SIZE block_size#define PS_SCANPART biosdisk_scanpart#define PS_REQUEST biosdisk_request#define B_CONST const#endif#ifdef __ATA__#include <dr-env.h>#include <devices.h>#include <errno.h>#include "ata.h"#include "disk.h"#include "partscan.h"#include "ata-ops.h"int ata_request(DWORD f, void *params); /* FIXME */#define PS_DEVICE struct ata_device#define PS_READ ata_read#define PS_HEADS heads#define PS_SECTS sectors#define PS_BLOCK_SIZE bytes_per_sector#define PS_SCANPART ata_scanpart#define PS_REQUEST ata_request#define B_CONST#endiftypedef struct{    BYTE  active;    BYTE  start_h;    BYTE  start_s;    BYTE  start_c;    BYTE  type;    BYTE  end_h;    BYTE  end_s;    BYTE  end_c;    DWORD lba_start;    DWORD lba_size;}__attribute__ ((packed)) PartTabl;#define PART_EMPTY     0x00#define PART_EXT_DOS   0x05#define PART_EXT_WIN   0x0F#define PART_EXT_LINUX 0x85#ifdef SHOWMSGstatic const struct { BYTE id; char *name; } partition_types[] ={    { 0x00, "Empty"             },    { 0x01, "FAT12"             },    { 0x04, "FAT16 up to 32 MB" },    { 0x05, "DOS extended"      },    { 0x06, "FAT16 over 32 MB"  },    { 0x07, "NTFS or HPFS"      },    { 0x0B, "FAT32"             },    { 0x0C, "FAT32 with LBA"    },    { 0x0E, "FAT16 with LBA"    },    { 0x0F, "Win extended"      },    { 0x82, "Linux Swap"        },    { 0x83, "Linux native"      },    { 0x85, "Linux extended"    },    { 0xFF, "unknown"           },    { 0, 0 }};static char *partname(BYTE id){    unsigned k;    for (k = 0; partition_types[k].name; k++)  	    if (partition_types[k].id == id) return partition_types[k].name;    return "unknown";}#endifstatic DWORD chs_to_lba(unsigned c, unsigned h, unsigned s, unsigned num_h, unsigned num_s){    return (DWORD) ((c * num_h + h) * num_s + s - 1);}static void check_lba(PartTabl *p, const PS_DEVICE *d){    DWORD lba_start, lba_size;    if (d->total_blocks / (d->PS_HEADS * d->PS_SECTS) > 1024) return; /* ...since we trust them */    lba_start = chs_to_lba(p->start_c + ((WORD) (p->start_s & 0xC0) << 2),                           p->start_h, p->start_s & 0x3F, d->PS_HEADS, d->PS_SECTS);    lba_size  = chs_to_lba(p->end_c + ((WORD) (p->end_s & 0xC0) << 2),                           p->end_h, p->end_s & 0x3F, d->PS_HEADS, d->PS_SECTS)              - lba_start + 1;    if ((lba_start != p->lba_start) || (lba_size != p->lba_size))        fd32_message("LBA values for the partition are not consistent with CHS values!\n");    p->lba_start = lba_start;    p->lba_size  = lba_size;}static int add_partition(const PS_DEVICE *d, const char *name, unsigned part, PartTabl *p){    #ifdef FD32DEV    int    res;    char  *dev_name;    #endif    DWORD  lba_start = p->lba_start;    DWORD  lba_end   = p->lba_start + p->lba_size - 1;    DWORD  type;    char   new_name[256];    PS_DEVICE  *new_d;        if ((p->type != PART_EMPTY)     && (p->type != PART_EXT_DOS)     && (p->type != PART_EXT_WIN)     && (p->type != PART_EXT_LINUX))    {        ksprintf(new_name, "%s%u", name, part);        type = FD32_BILOG;        if (part < 5)        {          if (p->active) type = FD32_BIACT;                    else type = FD32_BIPRI;        }        type |= (DWORD) p->type << 4;        #ifdef SHOWMSG        fd32_message("%s is %s (%02xh), Start: %lu, Size: %lu (%lu MiB)\n",                     new_name, partname(p->type), (unsigned) p->type, lba_start,                     lba_end - lba_start + 1,                     (DWORD) (((long long) (lba_end - lba_start + 1) * d->PS_BLOCK_SIZE) >> 20));        #endif        check_lba(p, d);        /* Allocate and initialize the private data structure */        if ((new_d = (PS_DEVICE *) fd32_kmem_get(sizeof(PS_DEVICE))) == NULL)            return -ENOMEM;        memcpy(new_d, d, sizeof(PS_DEVICE));        new_d->open_count = 0;        new_d->first_sector = lba_start;        new_d->total_blocks = lba_end - lba_start + 1;        new_d->type         = type;        new_d->multiboot_id = (d->multiboot_id & 0xFF00FFFF) | ((part - 1) << 24);        #ifdef FD32DEV        /* Register the new device to the FD32 kernel */        dev_name = (char *) fd32_kmem_get(strlen(new_name) + 1);        if (dev_name == NULL) return -ENOMEM;        strcpy(dev_name, new_name);        res = fd32_dev_register(PS_REQUEST, (void *) new_d, dev_name);        if (res < 0) return res;        #endif    }    return 0;}int PS_SCANPART(B_CONST PS_DEVICE *d, const char *dev_name){    PartTabl  tbl[4];    unsigned  k, part_num = 0;    int       res;    BYTE      buffer[d->PS_BLOCK_SIZE];    DWORD     ext_start = 0, ext_start1 = 0;        if (d->total_blocks / (d->PS_HEADS * d->PS_SECTS) > 1024)    {        fd32_message("Media is too big to be addressed using CHS (has more than 1024 cylinders).\n");        fd32_message("LBA values in the partition tables will be trusted.\n");    }    else    {        fd32_message("Media can be addressed using CHS (has up to 1024 cylinders).\n");        fd32_message("LBA values will be calculated from their respective CHS values.\n");    }    /* Read the MBR and copy the partition table in the tbl array */    res = PS_READ(d, 0, 1, buffer);    if (res < 0) return res;    memcpy(tbl, buffer + 446, 64);    /* If there are no active partitions, mark the first primary as active */    for (k = 0; k < 4; k++) if (tbl[k].active) break;    if (k == 4)        for (k = 0; k < 4; k++)            if ((tbl[k].type != PART_EMPTY)             && (tbl[k].type != PART_EXT_DOS)             && (tbl[k].type != PART_EXT_WIN)             && (tbl[k].type != PART_EXT_LINUX))            {                tbl[k].active = 0x80;                break;            }    /* Create partition devices for primary partitions */    for (k = 0; k < 4; k++) add_partition(d, dev_name, ++part_num, &tbl[k]);    /* Search for an extended partition in the primary partition table */    for (k = 0; k < 4; k++)    {        if ((tbl[k].type == PART_EXT_DOS)         || (tbl[k].type == PART_EXT_WIN)         || (tbl[k].type == PART_EXT_LINUX))        {            #ifdef SHOWMSG            fd32_message("%s%u is a %s partition\n", dev_name, k + 1,                         partname(tbl[k].type));            check_lba(&tbl[k], d);            #endif            ext_start = tbl[k].lba_start;            res = PS_READ(d, ext_start, 1, buffer);            if (res < 0) return res;            break;        }    }    /* Read extended partitions */    if (!ext_start) return 0;    for (;;)    {        memcpy(tbl, buffer + 446, 64);        for (k = 0; k < 4; k++)        {            if ((tbl[k].type != PART_EMPTY)             && (tbl[k].type != PART_EXT_DOS)             && (tbl[k].type != PART_EXT_WIN)             && (tbl[k].type != PART_EXT_LINUX))            {                part_num++;                tbl[k].lba_start += ext_start + ext_start1;            }            add_partition(d, dev_name, part_num, &tbl[k]);        }        for (k = 0; k < 4; k++)        {            if ((tbl[k].type == PART_EXT_DOS)             || (tbl[k].type == PART_EXT_WIN)             || (tbl[k].type == PART_EXT_LINUX))            {                ext_start1 = tbl[k].lba_start;                check_lba(&tbl[k], d);                res = PS_READ(d, ext_start + ext_start1, 1, buffer);                if (res < 0) return res;                break;            }        }        if (k == 4) break;    }    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -