天天看點

U-BOOT介紹以及disk子產品源碼分析(下)

Part_dos.c 檔案:

……

static void print_one_part (dos_partition_t *p, int ext_part_sector, int part_num)

{   //列印一個分區資訊

    ……

    printf ("%5d/t/t%10d/t%10d/t%2x%s/n",

        part_num, lba_start, lba_size, p->sys_ind,

        (is_extended (p->sys_ind) ? " Extd" : ""));

}

static int test_block_type(unsigned char *buffer)

{   //測試塊類型

    if((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||

        (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {

        return (-1);

    }   //不是dos塊

    if(strncmp(&buffer[DOS_PBR_FSTYPE_OFFSET],"FAT",3)==0)

        return DOS_PBR;

    return DOS_MBR;    

}

int test_part_dos (block_dev_desc_t *dev_desc)

{   //測試是否為dos塊

    unsigned char buffer[DEFAULT_SECTOR_SIZE];

    if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *) buffer) != 1) ||

        (buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||

        (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {

        return (-1);

    }

    return (0);

}

static void print_partition_extended (block_dev_desc_t *dev_desc, int ext_part_sector, int relative, int part_num)

{   //輸出與其擴充分區表有關的分區資訊

    ……

    //輸出所有主要/邏輯分區

    pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);

    for (i = 0; i < 4; i++, pt++) {//檔案系統不顯示MBR以外的分區

        if ((pt->sys_ind != 0) &&

            (ext_part_sector == 0 || !is_extended (pt->sys_ind)) ) {

            print_one_part (pt, ext_part_sector, part_num);

        }

        if ((ext_part_sector == 0) ||

            (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) ) {

            part_num++;

        }

    }

    //處理擴充分區

    pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);

    for (i = 0; i < 4; i++, pt++) {

        if (is_extended (pt->sys_ind)) {

            int lba_start = le32_to_int (pt->start4) + relative;

            print_partition_extended (dev_desc, lba_start,

                          ext_part_sector == 0  ? lba_start

                                    : relative,

                          part_num);

        }

    }

    return;

}

static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part_sector,    int relative, int part_num, int which_part, disk_partition_t *info)

{   //擷取與其擴充分區表有關的分區資訊

    ……

}

……

Part_iso.c 檔案:

int get_partition_info_iso_verb(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info, int verb)

{   //獲得iso裝置塊的分區資訊

    ……

    //第一部分必須是主要卷

    blkaddr=PVD_OFFSET;

    if (dev_desc->block_read (dev_desc->dev, PVD_OFFSET, 1, (ulong *) tmpbuf) != 1)

   return (-1);

    if(ppr->desctype!=0x01) {

        if(verb)

            printf ("** First descriptor is NOT a primary desc on %d:%d **/n",

                dev_desc->dev, part_num);

        return (-1);

    }

    if(strncmp(ppr->stand_ident,"CD001",5)!=0) {

        if(verb)

            printf ("** Wrong ISO Ident: %s on %d:%d **/n",

                ppr->stand_ident,dev_desc->dev, part_num);

        return (-1);

    }

    ……

    //尋找入口

    if(strncmp(pbr->ident_str,"EL TORITO SPECIFICATION",23)!=0) {

        if(verb)

            printf ("** Wrong El Torito ident: %s on %d:%d **/n",

                pbr->ident_str,dev_desc->dev, part_num);

        return (-1);

    }

    bootaddr=le32_to_int(pbr->pointer);

    PRINTF(" Boot Entry at: %08lX/n",bootaddr);

    if (dev_desc->block_read (dev_desc->dev, bootaddr, 1, (ulong *) tmpbuf) != 1) {

        if(verb)

            printf ("** Can't read Boot Entry at %lX on %d:%d **/n",

                bootaddr,dev_desc->dev, part_num);

        return (-1);

    }

……

    //找到有效入口,現在尋找分區

    entry_num=0;

    offset=0x20;

    sprintf (info->type, "U-Boot");

    switch(dev_desc->if_type) {

        case IF_TYPE_IDE:

        case IF_TYPE_ATAPI:

            sprintf (info->name, "hd%c%d/n", 'a' + dev_desc->dev, part_num);

            break;

        ……

        default:

            sprintf (info->name, "xx%c%d/n", 'a' + dev_desc->dev, part_num);

            break;

    }

    //bootcatalog (including validation Entry) 必須小于 2048Bytes

    while(offset<2048) {

        pide=(iso_init_def_entry_t *)&tmpbuf[offset];

        if ((pide->boot_ind==0x88) ||

            (pide->boot_ind==0x00)) {    //預設入口的id頭

            if(entry_num==part_num) { //找到分區

                goto found;

            }

            entry_num++; //記錄分區入口數

            offset+=0x20;

            continue;

        }

        if ((pide->boot_ind==0x90) ||  

            (pide->boot_ind==0x91) ||   

            (pide->boot_ind==0x44)) {   

            offset+=0x20; //跳過不使用的入口

        }

        else {

            if(verb)

                printf ("** Partition %d not found on device %d **/n",

                    part_num,dev_desc->dev);

            return(-1);

        }

    }

    ……

    newblkaddr=le32_to_int(pide->rel_block_addr);

    info->start=newblkaddr;

    PRINTF(" part %d found @ %lx size %lx/n",part_num,newblkaddr,info->size);

    return 0;

}

int get_partition_info_iso(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info)

{

    return(get_partition_info_iso_verb(dev_desc, part_num, info, 1));

}

void print_part_iso(block_dev_desc_t * dev_desc)

{   //列印分區資訊

    disk_partition_t info;

    int i;

    if(get_partition_info_iso_verb(dev_desc,0,&info,0)==-1) {

        printf("** No boot partition found on device %d **/n",dev_desc->dev);

        return;

    }

    printf("Part   Start     Sect x Size Type/n");

    i=0;

    do {

        printf (" %2d %8ld %8ld %6ld %.32s/n",

            i, info.start, info.size, info.blksz, info.type);

        i++;

    } while (get_partition_info_iso_verb(dev_desc,i,&info,0)!=-1);

}

int test_part_iso (block_dev_desc_t *dev_desc)

{   測試是否為iso分區

    disk_partition_t info;

    return(get_partition_info_iso_verb(dev_desc,0,&info,0));

}

Part_mac.c 檔案:

int test_part_mac (block_dev_desc_t *dev_desc)

{   //檢查是否為有效的mac分區

    ……

    if (part_mac_read_ddb (dev_desc, &ddesc)) {//讀塊錯誤,或無有效資訊

        return (-1);    }

    n = 1;  //假設最少有一個分區

    for (i=1; i<=n; ++i) {

        if ((dev_desc->block_read(dev_desc->dev, i, 1, (ulong *)&mpart) != 1) ||

            (mpart.signature != MAC_PARTITION_MAGIC) ) {

            return (-1);

        }

        n = mpart.map_count;    更新分區數

    }

    return (0);

}

void print_part_mac (block_dev_desc_t *dev_desc)

{   //輸出mac分區資訊

    ……

    if (part_mac_read_ddb (dev_desc, &ddesc)) {

        return;

    }

    n  = ddesc.blk_count;

……

    printf ("Block Size=%d, Number of Blocks=%d, "

        "Total Capacity: %ld.%ld MB = %ld.%ld GB/n"

        "DeviceType=0x%x, DeviceId=0x%x/n/n"

        "   #:                 type name"

        "                   length   base       (size)/n",

        ddesc.blk_size,

        ddesc.blk_count,

        mb.quot, mb.rem, gb.quot, gb.rem,

        ddesc.dev_type, ddesc.dev_id

        );

    n = 1;  //假設最少有一個分區

    for (i=1; i<=n; ++i) {

        ……

        printf ("%20.32s %-18.32s %10u @ %-10u (%3ld%c)/n",

            mpart.type,

            mpart.name,

            mpart.block_count,

            mpart.start_block,

            bytes, c

            );

    }

    return;

}

static int part_mac_read_ddb (block_dev_desc_t *dev_desc, mac_driver_desc_t *ddb_p)

{   //讀取裝置描述塊資訊

    ……

    if (ddb_p->signature != MAC_DRIVER_MAGIC) {

#if 0

        printf ("** Bad Signature: expected 0x%04x, got 0x%04x/n",

            MAC_DRIVER_MAGIC, ddb_p->signature);

#endif

        return (-1);

    }

    return (0);

}

static int part_mac_read_pdb (block_dev_desc_t *dev_desc, int part, mac_partition_t *pdb_p)

{   //讀取分區描述塊資訊

    int n = 1;

    for (;;) {  //必須從第一個分區開始讀描述塊,隻有這樣才能知道一共有多少個分區

        if (dev_desc->block_read (dev_desc->dev, n, 1, (ulong *)pdb_p) != 1) {

            printf ("** Can't read Partition Map on %d:%d **/n",

                dev_desc->dev, n);

            return (-1);

        }

        if (pdb_p->signature != MAC_PARTITION_MAGIC) {

            printf ("** Bad Signature on %d:%d: "

                "expected 0x%04x, got 0x%04x/n",

                dev_desc->dev, n, MAC_PARTITION_MAGIC, pdb_p->signature);

            return (-1);

        }

        if (n == part)

            return (0);

        if ((part < 1) || (part > pdb_p->map_count)) {

            printf ("** Invalid partition %d:%d [%d:1...%d:%d only]/n",

                dev_desc->dev, part,

                dev_desc->dev,

                dev_desc->dev, pdb_p->map_count);

            return (-1);

        }

        n = part;   //更新分區數

    }

}

int get_partition_info_mac (block_dev_desc_t *dev_desc, int part, disk_partition_t *info)

{   //擷取mac分區的資訊

    mac_driver_desc_t   ddesc;

    mac_partition_t     mpart;

    if (part_mac_read_ddb (dev_desc, &ddesc)) {

        return (-1);

    }

    info->blksz = ddesc.blk_size;

    if (part_mac_read_pdb (dev_desc, part, &mpart)) {

        return (-1);

    }

    info->start = mpart.start_block;

    info->size  = mpart.block_count;

    memcpy (info->type, mpart.type, sizeof(info->type));

    memcpy (info->name, mpart.name, sizeof(info->name));

    return (0);

}

四.常用 U-BOOT 指令介紹

1.list 得到所有指令清單

2.help: help usb, 列出USB功能的使用說明

3.ping:注:隻能開發闆PING别的機器

4.setenv: 設定互環境變量:

5.setenv serverip 192.168.0.1

6.setenv ipaddr 192.168.0.56

7.setenv bootcmd ‘tftp 32000000 vmlinux; kgo 32000000 ’

8.saveenv: 儲存環境變量

9.在設定好環境變量以後, 儲存變量值

10.tftp: tftp 32000000 vmlinux, 把server(IP=環境變量中設定的serverip)中/tftpdroot/ 下的vmlinux通過TFTP讀入到實體記憶體32000000處。

11.kgo: 起動沒有壓縮的linux核心,kgo 32000000

12.bootm:起動UBOOT  TOOLS制作的壓縮LINUX核心, bootm 3200000

13.protect: 對FLASH進行寫保護或取消寫保護, protect on 1:0-3(就是對第一塊FLASH的0-3扇區進行保護),protect off 1:0-3取消寫保護

14.erase: 删除FLASH的扇區, erase 1:0-2(就是對每一塊FLASH的0-2扇區進行删除)

15.cp: 在記憶體中複制内容, cp 32000000 0 40000(把記憶體中0x32000000開始的0x40000位元組複制到0x0處)

16.mw: 對RAM中的内容寫操作, mw 32000000 ff 10000(把記憶體0x32000000開始的0x10000位元組設為0xFF)

17.md: 修改RAM中的内容, md 32000000(記憶體的起始位址)

18.usb:

lusb start: 起動usb 功能

lusb info: 列出裝置

lusb scan: 掃描usb storage(u 盤)裝置

19.fatls:列出DOS FAT檔案系統, 如:fatls usb 0列出第一塊U盤中的檔案

20.fatload: 讀入FAT中的一個檔案,如:fatload usb 0:0 32000000 aa.txt

21.把USB中的aa.txt 讀到實體記憶體0x32000000處!

22.flinfo: 列出flash的資訊

23.loadb: 準備用KERMIT協定接收來自kermit或超級終端傳送的檔案。

24.nfs: nfs 32000000 192.168.0.2:aa.txt , 把192.168.0.2(LINUX 的NFS檔案系統)中的NFS檔案系統中的aa.txt 讀入記憶體0x32000000處。