?? build.c
字號:
/** linux/tools/build.c** (C) 1991 Linus Torvalds*//** This file builds a disk-image from three different files:** - bootsect: max 510 bytes of 8086 machine code, loads the rest* - setup: max 4 sectors of 8086 machine code, sets up system parm* - system: 80386 code for actual system** It does some checking that all files are of the correct type, and* just writes the result to stdout, removing headers and padding to* the right amount. It also writes some system data to stderr.*//** 該程序從三個不同的程序中創(chuàng)建磁盤映象文件:** - bootsect:該文件的8086 機器碼最長為510 字節(jié),用于加載其它程序。* - setup:該文件的8086 機器碼最長為4 個磁盤扇區(qū),用于設置系統(tǒng)參數(shù)。* - system:實際系統(tǒng)的80386 代碼。** 該程序首先檢查所有程序模塊的類型是否正確,并將檢查結果在終端上顯示出來,* 然后刪除模塊頭部并擴充大正確的長度。該程序也會將一些系統(tǒng)數(shù)據(jù)寫到stderr。*//** Changes by tytso to allow root device specification*//** tytso 對該程序作了修改,以允許指定根文件設備。*/#include <stdio.h> /* fprintf */ /* 使用其中的fprintf() */#include <string.h> /* 字符串操作 */#include <stdlib.h> /* contains exit */ /* 含有exit() */#include <sys/types.h> /* unistd.h needs this */ /* 供unistd.h 使用 */#include <sys/stat.h> /* 文件狀態(tài)信息結構 */#include <linux/fs.h> /* 文件系統(tǒng) */#include <unistd.h> /* contains read/write */ /* 含有read()/write() */#include <fcntl.h> /* 文件操作模式符號常數(shù) */#define MINIX_HEADER 32 // minix 二進制模塊頭部長度為32 字節(jié)。#define GCC_HEADER 1024 // GCC 頭部信息長度為1024 字節(jié)。#define SYS_SIZE 0x2000 // system 文件最長節(jié)數(shù)(字節(jié)數(shù)為SYS_SIZE*16=128KB)。#define DEFAULT_MAJOR_ROOT 3 // 默認根設備主設備號 - 3(硬盤)。#define DEFAULT_MINOR_ROOT 6 // 默認根設備次設備號 - 6(第2 個硬盤的第1 分區(qū))。/* max nr of sectors of setup: don't change unless you also change* bootsect etc *//* 下面指定setup 模塊占的最大扇區(qū)數(shù):不要改變該值,除非也改變bootsect 等相應文件。#define SETUP_SECTS 4 // setup 最大長度為4 個扇區(qū)(4*512 字節(jié))。*/#define STRINGIFY(x) #x // 用于出錯時顯示語句中表示扇區(qū)數(shù)。//// 顯示出錯信息,并終止程序。voiddie (char *str){ fprintf (stderr, "%s\n", str); exit (1);}// 顯示程序使用方法,并退出。voidusage (void){ die ("Usage: build bootsect setup system [rootdev] [> image]");}intmain (int argc, char **argv){ int i, c, id; char buf[1024]; char major_root, minor_root; struct stat sb;// 如果程序命令行參數(shù)不是4 或5 個,則顯示程序用法并退出。 if ((argc != 4) && (argc != 5)) usage ();// 如果參數(shù)是5 個,則說明帶有根設備名。 if (argc == 5) {// 如果根設備名是軟盤("FLOPPY"),則取該設備文件的狀態(tài)信息,若出錯則顯示信息,退出。 if (strcmp (argv[4], "FLOPPY")) { if (stat (argv[4], &sb)) { perror (argv[4]); die ("Couldn't stat root device."); }// 若成功則取該設備名狀態(tài)結構中的主設備號和次設備號。 major_root = MAJOR (sb.st_rdev); minor_root = MINOR (sb.st_rdev); } else {// 否則讓主設備號和次設備號取0。 major_root = 0; minor_root = 0; }// 若參數(shù)只有4 個,則讓主設備號和次設備號等于系統(tǒng)默認的根設備。 } else { major_root = DEFAULT_MAJOR_ROOT; minor_root = DEFAULT_MINOR_ROOT; }// 在標準錯誤終端上顯示所選擇的根設備主、次設備號。 fprintf (stderr, "Root device is (%d, %d)\n", major_root, minor_root);// 如果主設備號不等于2(軟盤)或3(硬盤),也不等于0(取系統(tǒng)默認根設備),則顯示出錯信息,退出。 if ((major_root != 2) && (major_root != 3) && (major_root != 0)) { fprintf (stderr, "Illegal root device (major = %d)\n", major_root); die ("Bad root device --- major #"); }// 初始化buf 緩沖區(qū),全置0。 for (i = 0; i < sizeof buf; i++) buf[i] = 0;// 以只讀方式打開參數(shù)1 指定的文件(bootsect),若出錯則顯示出錯信息,退出。 if ((id = open (argv[1], O_RDONLY, 0)) < 0) die ("Unable to open 'boot'");// 讀取文件中的minix 執(zhí)行頭部信息(參見列表后說明),若出錯則顯示出錯信息,退出。 if (read (id, buf, MINIX_HEADER) != MINIX_HEADER) die ("Unable to read header of 'boot'");// 0x0301 - minix 頭部a_magic 魔數(shù);0x10 - a_flag 可執(zhí)行;0x04 - a_cpu, Intel 8086 機器碼。 if (((long *) buf)[0] != 0x04100301) die ("Non-Minix header of 'boot'");// 判斷頭部長度字段a_hdrlen(字節(jié))是否正確。(后三字節(jié)正好沒有用,是0) if (((long *) buf)[1] != MINIX_HEADER) die ("Non-Minix header of 'boot'");// 判斷數(shù)據(jù)段長a_data 字段(long)內(nèi)容是否為0。 if (((long *) buf)[3] != 0) die ("Illegal data segment in 'boot'");// 判斷堆a_bss 字段(long)內(nèi)容是否為0。 if (((long *) buf)[4] != 0) die ("Illegal bss in 'boot'");// 判斷執(zhí)行點a_entry 字段(long)內(nèi)容是否為0。 if (((long *) buf)[5] != 0) die ("Non-Minix header of 'boot'");// 判斷符號表長字段a_sym 的內(nèi)容是否為0。 if (((long *) buf)[7] != 0) die ("Illegal symbol table in 'boot'");// 讀取實際代碼數(shù)據(jù),應該返回讀取字節(jié)數(shù)為512 字節(jié)。 i = read (id, buf, sizeof buf); fprintf (stderr, "Boot sector %d bytes.\n", i); if (i != 512) die ("Boot block must be exactly 512 bytes");// 判斷boot 塊0x510 處是否有可引導標志0xAA55。 if ((*(unsigned short *) (buf + 510)) != 0xAA55) die ("Boot block hasn't got boot flag (0xAA55)");// 引導塊的508,509 偏移處存放的是根設備號。 buf[508] = (char) minor_root; buf[509] = (char) major_root;// 將該boot 塊512 字節(jié)的數(shù)據(jù)寫到標準輸出stdout,若寫出字節(jié)數(shù)不對,則顯示出錯信息,退出。 i = write (1, buf, 512); if (i != 512) die ("Write call failed");// 最后關閉bootsect 模塊文件。 close (id);// 現(xiàn)在開始處理setup 模塊。首先以只讀方式打開該模塊,若出錯則顯示出錯信息,退出。 if ((id = open (argv[2], O_RDONLY, 0)) < 0) die ("Unable to open 'setup'");// 讀取該文件中的minix 執(zhí)行頭部信息(32 字節(jié)),若出錯則顯示出錯信息,退出。 if (read (id, buf, MINIX_HEADER) != MINIX_HEADER) die ("Unable to read header of 'setup'");// 0x0301 - minix 頭部a_magic 魔數(shù);0x10 - a_flag 可執(zhí)行;0x04 - a_cpu, Intel 8086 機器碼。 if (((long *) buf)[0] != 0x04100301) die ("Non-Minix header of 'setup'");// 判斷頭部長度字段a_hdrlen(字節(jié))是否正確。(后三字節(jié)正好沒有用,是0) if (((long *) buf)[1] != MINIX_HEADER) die ("Non-Minix header of 'setup'");// 判斷數(shù)據(jù)段長a_data 字段(long)內(nèi)容是否為0。 if (((long *) buf)[3] != 0) die ("Illegal data segment in 'setup'");// 判斷堆a_bss 字段(long)內(nèi)容是否為0。 if (((long *) buf)[4] != 0) die ("Illegal bss in 'setup'");// 判斷執(zhí)行點a_entry 字段(long)內(nèi)容是否為0。 if (((long *) buf)[5] != 0) die ("Non-Minix header of 'setup'");// 判斷符號表長字段a_sym 的內(nèi)容是否為0。 if (((long *) buf)[7] != 0) die ("Illegal symbol table in 'setup'");// 讀取隨后的執(zhí)行代碼數(shù)據(jù),并寫到標準輸出stdout。 for (i = 0; (c = read (id, buf, sizeof buf)) > 0; i += c) if (write (1, buf, c) != c) die ("Write call failed");//關閉setup 模塊文件。 close (id);// 若setup 模塊長度大于4 個扇區(qū),則算出錯,顯示出錯信息,退出。 if (i > SETUP_SECTS * 512) die ("Setup exceeds " STRINGIFY (SETUP_SECTS) " sectors - rewrite build/boot/setup");// 在標準錯誤stderr 顯示setup 文件的長度值。 fprintf (stderr, "Setup is %d bytes.\n", i);// 將緩沖區(qū)buf 清零。 for (c = 0; c < sizeof (buf); c++) buf[c] = '\0';// 若setup 長度小于4*512 字節(jié),則用\0 將setup 填足為4*512 字節(jié)。 while (i < SETUP_SECTS * 512) { c = SETUP_SECTS * 512 - i; if (c > sizeof (buf)) c = sizeof (buf); if (write (1, buf, c) != c) die ("Write call failed"); i += c; }// 下面處理system 模塊。首先以只讀方式打開該文件。 if ((id = open (argv[3], O_RDONLY, 0)) < 0) die ("Unable to open 'system'");// system 模塊是GCC 格式的文件,先讀取GCC 格式的頭部結構信息(linux 的執(zhí)行文件也采用該格式)。 if (read (id, buf, GCC_HEADER) != GCC_HEADER) die ("Unable to read header of 'system'");// 該結構中的執(zhí)行代碼入口點字段a_entry 值應為0。 if (((long *) buf)[5] != 0) die ("Non-GCC header of 'system'");// 讀取隨后的執(zhí)行代碼數(shù)據(jù),并寫到標準輸出stdout。 for (i = 0; (c = read (id, buf, sizeof buf)) > 0; i += c) if (write (1, buf, c) != c) die ("Write call failed");// 關閉system 文件,并向stderr 上打印system 的字節(jié)數(shù)。 close (id); fprintf (stderr, "System is %d bytes.\n", i);// 若system 代碼數(shù)據(jù)長度超過SYS_SIZE 節(jié)(或128KB 字節(jié)),則顯示出錯信息,退出。 if (i > SYS_SIZE * 16) die ("System is too big"); return (0);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -