U-BOOT介绍以及disk模块源码分析
Part.c文件: void dev_print (block_dev_desc_t *dev_desc) {//主要用來向用戶報告設備信息 …… if (dev_desc->type==DEV_TYPE_UNKNOWN) {//設備未知 puts ("not available/n"); return; } …… puts ("??????????? Type: "); if (dev_desc->removable)??? //設備可移除 puts ("Removable "); switch (dev_desc->type & 0x1F) {??? //輸出設備類型 case DEV_TYPE_HARDDISK: puts ("Hard Disk"); break; case DEV_TYPE_CDROM:??? puts ("CD ROM"); break; case DEV_TYPE_OPDISK:? puts ("Optical Device"); break; case DEV_TYPE_TAPE:???? puts ("Tape"); break; default:??????? printf ("# %02X #", dev_desc->type & 0x1F); break; } puts ("/n"); if ((dev_desc->lba * dev_desc->blksz)>0L) { ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem; lbaint_t lba; lba = dev_desc->lba; lba512 = (lba * (dev_desc->blksz/512)); mb = (10 * lba512) / 2048; /* 2048 = (1024 * 1024) / 512 MB */ /* round to 1 digit */ mb_quot = mb / 10; mb_rem = mb - (10 * mb_quot); gb = mb / 1024; gb_quot = gb / 10; gb_rem = gb - (10 * gb_quot); …… } else { puts ("??????????? Capacity: not available/n");?? } } …… void init_part (block_dev_desc_t * dev_desc)??? //對分區iso,mac,dos,amiga進行初始化 { #ifdef CONFIG_ISO_PARTITION //對應iso分區 …… #endif #ifdef CONFIG_MAC_PARTITION //對應mac分區 …… #endif #ifdef CONFIG_DOS_PARTITION //對應dos分區 …… #endif #ifdef CONFIG_AMIGA_PARTITION//對應amiga分區 …… #endif } int get_partition_info (block_dev_desc_t *dev_desc, int part, disk_partition_t *info) {?? //獲得不同分區的分區信息 switch (dev_desc->part_type) { #ifdef CONFIG_MAC_PARTITION //對應mac分區,以下略 …… #endif …… default: break; } return (-1); } static void print_part_header (const char *type, block_dev_desc_t * dev_desc) {?? //輸出設備、分區類型,如IDE, SCSI, ATAPI, USB, DOC, UNKNOWN puts ("/nPartition Map for "); switch (dev_desc->if_type) { case IF_TYPE_IDE: puts ("IDE"); break; …… default:??????? puts ("UNKNOWN"); break; } printf (" device %d --?? Partition Type: %s/n/n", dev_desc->dev, type); } void print_part (block_dev_desc_t * dev_desc) {?? //輸出分區信息 switch (dev_desc->part_type) { #ifdef CONFIG_MAC_PARTITION …… #endif #ifdef CONFIG_DOS_PARTITION …… #endif #ifdef CONFIG_ISO_PARTITION …… #endif #ifdef CONFIG_AMIGA_PARTITION …… #endif } puts ("## Unknown partition table/n"); } Part_amiga文件: static void bcpl_strcpy(char *to, char *from) {?? //將bcpl轉換成c string int len = *from++; while (len) {??? *to++ = *from++;??? len--;??? } *to = 0; } static void bstr_print(char *string) {?? //輸出一個bcpl字符串。Bcpl字符串第一個byte保存了該字符串的長度 …… } int sum_block(struct block_header *header) {?? //計算一個塊的大小,塊以0結束 …… for (i = 0; i < header->summed_longs; i++) sum += *block++; return (sum != 0); } static void print_disk_type(u32 disk_type) {?? //輸出amigaOS 磁盤類型,一般由四個字節表示,例如DOS/0表示original file system,SFS/0表示SmartFileSystem,DOS/1表示FFS. char buffer[6]; buffer[0] = (disk_type & 0xFF000000)>>24; buffer[1] = (disk_type & 0x00FF0000)>>16; buffer[2] = (disk_type & 0x0000FF00)>>8; buffer[3] = '//'; buffer[4] = (disk_type & 0x000000FF) + '0'; buffer[5] = 0; printf("%s", buffer); } static void print_part_info(struct partition_block *p) {?? //輸出給定分區塊內的信息 …… bstr_print(p->drive_name); printf("%6d/t%6d/t", g->low_cyl * g->block_per_track * g->surfaces , (g->high_cyl - g->low_cyl + 1) * g->block_per_track * g->surfaces - 1); print_disk_type(g->dos_type); printf("/t%5d/n", g->boot_priority); } struct rigid_disk_block *get_rdisk(block_dev_desc_t *dev_desc) {?? //尋找Rigid Disk塊。該塊必須位于設備的最前面的16個塊中 …… if (res == 1) { struct rigid_disk_block *trdb = (struct rigid_disk_block *)block_buffer; if (trdb->id == AMIGA_ID_RDISK) { PRINTF("Rigid disk block suspect at %d, checking checksum/n",i); if (sum_block((struct block_header *)block_buffer) == 0) { PRINTF("FOUND/n"); memcpy(&rdb, trdb, sizeof(struct rigid_disk_block)); return (struct rigid_disk_block *)&rdb; } } } } PRINTF("Done scanning, no RDB found/n"); return NULL; } struct bootcode_block *get_bootcode(block_dev_desc_t *dev_desc) {?? //尋找啟動代碼,它必須在塊設備前16個塊中,或者在Ridgid塊中 …… PRINTF("Scanning for BOOT from 0 to %d/n", limit); for (i = 0; i < limit; i++) { ulong res = dev_desc->block_read(dev_desc->dev, i, 1, (ulong *)block_buffer); if (res == 1) { struct bootcode_block *boot = (struct bootcode_block *)block_buffer; if (boot->id == AMIGA_ID_BOOT) { PRINTF("BOOT block at %d, checking checksum/n", i); if (sum_block((struct block_header *)block_buffer) == 0) { PRINTF("Found valid bootcode block/n"); memcpy(&bootcode, boot, sizeof(struct bootcode_block)); return &bootcode; } } } } PRINTF("No boot code found on disk/n"); return 0; } int test_part_amiga(block_dev_desc_t *dev_desc) {?? //測試給定分區是否有amiga分區表/rigid塊 …… PRINTF("test_part_amiga: Testing for an Amiga RDB partition/n"); rdb = get_rdisk(dev_desc); if (rdb) { bootcode = get_bootcode(dev_desc); if (bootcode) PRINTF("test_part_amiga: bootable Amiga disk/n"); else PRINTF("test_part_amiga: non-bootable Amiga disk/n"); return 0; } else { PRINTF("test_part_amiga: no RDB found/n"); return -1; } } static struct partition_block *find_partition(block_dev_desc_t *dev_desc, int partnum) {?? //尋找指定分區號的分區 …… PRINTF("Trying to find partition block %d/n", partnum); …… while (block != 0xFFFFFFFF) { ulong res = dev_desc->block_read(dev_desc->dev, block, 1, (ulong *)block_buffer); if (res == 1) { p = (struct partition_block *)block_buffer; if (p->id == AMIGA_ID_PART) { PRINTF("PART block suspect at 0x%x, checking checksum/n",block); if (sum_block((struct block_header *)p) == 0) { if (partnum == 0) break; else { partnum--; block = p->next; } } } else block = 0xFFFFFFFF; } else block = 0xFFFFFFFF; } …… return (struct partition_block *)block_buffer; } int get_partition_info_amiga (block_dev_desc_t *dev_desc, int part, disk_partition_t *info) {?? //獲取一個分區的信息 …… if (!p) return -1; g = (struct amiga_part_geometry *)&(p->environment); info->start = g->low_cyl * g->block_per_track * g->surfaces; info->size = (g->high_cyl - g->low_cyl + 1) * g->block_per_track * g->surfaces - 1; info->blksz = rdb.block_bytes; bcpl_strcpy(info->name, p->drive_name); disk_type = g->dos_type; info->type[0] = (disk_type & 0xFF000000)>>24; info->type[1] = (disk_type & 0x00FF0000)>>16; info->type[2] = (disk_type & 0x0000FF00)>>8; info->type[3] = '//'; info->type[4] = (disk_type & 0x000000FF) + '0'; info->type[5] = 0; return 0; } void print_part_amiga (block_dev_desc_t *dev_desc) {?? //輸出分區信息 …… PRINTF("print_part_amiga: Scanning partition list/n"); block = rdb->partition_list; PRINTF("print_part_amiga: partition list at 0x%x/n", block); printf("Summary: DiskBlockSize: %d/n" "????????? Cylinders??? : %d/n" "????????? Sectors/Track: %d/n" "????????? Heads??????? : %d/n/n", rdb->block_bytes, rdb->cylinders, rdb->sectors, rdb->heads); printf("???????????????? First?? Num. /n" "Nr. Part. Name Block?? Block Type??????? Boot Priority/n"); …… boot = get_bootcode(dev_desc); if (boot) {??? printf("Disk is bootable/n");??? } }
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; /* is PBR */
??? return DOS_MBR;???? /* Is 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);
??????? }
??????? /* Reverse engr the fdisk part# assignment rule! */
??????? 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) ||?? /* Section Header Entry */
??????????? (pide->boot_ind==0x91) ||??? /* Section Header Entry (last) */
??????????? (pide->boot_ind==0x44)) {??? /* Extension Indicator */
??????????? 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)) {
??????? /* error reading Driver Desriptor Block, or no valid Signature */
??????? 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處。
總結
以上是生活随笔為你收集整理的U-BOOT介绍以及disk模块源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uboot中IDE移植
- 下一篇: Linux 关于动态链接库以及静态链接库