2010年3月15日

舊文新貼-NetBSD與ARM的邂逅~

ARM NetBSD 手記:

總整理:

Linux 有許多優點,但也有許多缺點,他最大的缺點,就是沒什麼隱私,
你有修改過,就必須按照規矩放出來給大家看,儘管有許多人規避它,
但現階段,這個規矩還不能改變,而 NetBSD 承襲了 BSD 的優點,
完全的自由,完全的合法,你用它惡搞,當商品,都不管你。
而且因為 BSD 社群的習慣性(比較保守),它的程式碼都有不錯的穩定性,
雖然因此來說效率較差,但的確是值得當作 base 來開發。

BSD 的主要缺點就是支援嚴重缺乏,舉個例子,
當 Linux 都已經把許多 USB 設備驅動起來,
甚至 webcam 和 Videl For Linux 被大家開發到非常容易就可以使用,
而 FlashROM 的驅動,甚至還設計了 MTD 還有 JFFS、YAFFS 之類的 FS,
BSD 在這方面是完全沒有的。

因此,這樣的東西,假以時日,是可以成為非常不錯的 base,有無限的潛力。

NetBSD 在 ARM 上的環境可以用賓士車來形容,
從 Compiler、Kernel、rootfs、Application 全包,
而且寫好 build.sh 這樣的 script,
要安裝、編譯都非常容易,而且整個編排非常有系統,
對於初踏入嵌入式系統的人,會好理解得多,這是很棒的事情。

編譯方式如下:

1.編譯出 Compiler Tools

ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-3.0.1/source/sets/

下載
  • src.tgz
  • syssrc.tgz
  • share.tgz
  • gnusrc.tgz

到 / 解壓縮,它會解到 /usr/src

而它的編譯環境很棒,是跨平台的,
目前看起來,Linux 和 FreeBSD 都可以建立,
需要注意的是,在 Linux 上建立時,
用 gcc-4.1.2 會編譯失敗,用 gcc-3.3、gcc-3.4 則非常正常,
因此要先將 gcc...等幾個 4.1 的編譯程式改 link 到 gcc-3.x,
執行如下:
# cd /usr/bin
# rm cpp gcc g++
# ln -s gcc-3.4 gcc
# ln -s g++-3.4 g++
# ln -s cpp-3.4 cpp


要復原則執行
# cd /usr/bin
# rm cpp gcc g++
# ln -s gcc-4.1 gcc
# ln -s g++-4.1 g++
# ln -s cpp-4.1 cpp

(要視目前版本而修正)

此外,它編譯時會需要 zlib.h,
在 Debian 上,它是在 zlib1g-dev 這個套件中。
此外,當出現
terminal.o(.text+0x40): In function `terminal_begin_using_terminal':
的錯誤時,是因為在 Debian 上,它需要 libncurses5-dev。

補充一點,build.sh 在執行時會有問題,問題是發生在 TOP 這個變數,
因此要編輯 build.sh,把
TOP=$(/bin/pwd -P 2>/dev/null)
改為
TOP=/usr/src

2.開始建立環境
# cd /usr/src
# mkdir ../obj
# chmod 755 build.sh
# ./build.sh -m evbarm tools


-m 表示指定編譯環境是 evbarm
tools 表示要編譯出 tools

說明可以執行 build.sh --help 後觀看。

另外,我們也可以用較為複雜的參數來編譯,雖然較為複雜,不過我們可以自行指定路徑,如下:
# ./build.sh -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release tools

-O /home/2410/netbsd/obj //obj 目錄
-T /usr/local/arm/netbsd //Compiler 目錄
-D /home/2410/netbsd/build //build 目錄
-R /home/2410/netbsd/release //release 目錄

此外,我在後來編譯的環境改用 coLinux 來進行,coLinux 安裝後和一般的 Debian 相同,
唯一差別是似乎不支援 kernel module,
而使用 coLinux 編譯環境時,以下是我使用到的 coLinux base 安裝套件列表:
aee ee bzip2 g++ gcc joe nfs-user-server libncurses5-dev ssh tcsh vsftpd zlib1g-dev make locales less

再來,前面提到可用較為複雜的參數來編譯,我們可以將整個 NetBSD 連同所有 evbarm source 都編譯出來,
整個參數如下:
./build.sh -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release tools && \
./build.sh -U -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release build && \
./build.sh -U -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release release && \
./build.sh -U -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release kernel=SMDK2410_INSTALL


-u //不要執行 make clean
-U //不需要 root 權限
-O /home/2410/netbsd/obj //obj 目錄
-T /usr/local/arm/netbsd //Compiler 目錄
-D /home/2410/netbsd/build //build 目錄
-R /home/2410/netbsd/release //release 目錄

再修正
./build.sh -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release tools && \
./build.sh -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release build && \
./build.sh -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release release && \
./build.sh -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release kernel=SMDK2410_INSTALL


這樣會編譯出
build ;也就是 obj 目錄,將全部東西 build 一次,包括 fs,application,kernel...等
release ;內含完整 evbarm 的 source,也就是會將上面的 fs,application 打包,kernel 檔也通通會編譯
kernel ;目前沒改過,則會編譯出預設的 kernel

3.要正式編譯 NetBSD 的 kernel 之前,NetBSD 製作出來後會無法開機,要如下修改才能進入 kernel:

sys/arch/evbarm/smdk2xx0/smdk2410_start.S


......
_C_LABEL(smdk2410_start):
/* Disable interrupt */
mrs r0, cpsr
orr r0, r0, #I32_bit
msr cpsr, r0

#ifdef SMDK2XX0_CLOCK_CONFIG
adr r4, clock_config_data
......

改為
......
_C_LABEL(smdk2410_start):
/* Disable interrupt */
mrs r0, cpsr
orr r0, r0, #I32_bit
msr cpsr, r0

/* flush v4 I/D caches */
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

/* disable MMU stuff and caches */
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
mcr p15, 0, r0, c1, c0, 0

#ifdef SMDK2XX0_CLOCK_CONFIG
adr r4, clock_config_data
......


另外,它預設的 SDRAM size 是和板子不合的,
僅僅是不合就算了,可是因為我們的 image 有 27 MB,
不合的 SDSRAM size 造成 RAM 不夠,執行時就會有問題,
而修改很容易,如下:

sys/arch/evbarm/smdk2xx0/smdk2410_machdep.c


......
#ifndef SDRAM_START
#define SDRAM_START S3C2410_SDRAM_START
#endif
#ifndef SDRAM_SIZE
#define SDRAM_SIZE (32*1024*1024)
#endif

......


改為
......
#ifndef SDRAM_START
#define SDRAM_START S3C2410_SDRAM_START
#endif
#ifndef SDRAM_SIZE
#define SDRAM_SIZE (64*1024*1024)
#endif

......


如果我們要讓它支援超過 3M 的 rootfs 時,需要如下修改:
修改程式碼如下:
sys/arch/evbarm/smdk2xx0/smdk2410_machdep.c
.....
#define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000)
.....
#define KERNEL_PT_KERNEL_NUM 2 /* L2 tables for mapping kernel VM */
.....


改為
.....
#define KERNEL_VM_BASE (KERNEL_BASE + 0x02000000)
.....
#define KERNEL_PT_KERNEL_NUM 8 /* L2 tables for mapping kernel VM */
.....


設定部份為:
sys/arch/evbarm/conf/INSTALL
options MEMORY_DISK_ROOT_SIZE=6510
改為
options MEMORY_DISK_ROOT_SIZE=49152
NetBSD 對 RAM Disk 的大小是有設定的,它的設定是定義在
/usr/src/sys/arch/evbarm/conf/INSTALL

要知道為何是這個設定檔,我們看到
/usr/src/sys/arch/evbarm/conf/SMDK2410_INSTALL

它裡面只有 include 其他檔案,一個是
/usr/src/sys/arch/evbarm/conf/SMDK2410

另一個是
/usr/src/sys/arch/evbarm/conf/INSTALL

而 /usr/src/sys/arch/evbarm/conf/INSTALL 裡面定義的,
就是 RAM Disk 的大小和一些嵌入式系統的 RAM 設定,
而它預設值是 6510,其實就是 3 MB 再大一點點,
而這個值的算法可以參考「製作嵌入式晶片s3c2410板卡的NetBSD啟動鏡像」,
它是
6510 x 512 / 1024 = 6150 / 2 =3075k

也就是說,6510 / 2 / 1024,就是約略的 MB 數。

4.要編譯 NetBSD 的 kernel 十分容易
將 /usr/src/tooldir.Linux-2.6.17-unknown/bin 加入 PATH 中
(tooldir.Linux-2.6.17-unknown 是編譯環境時,依據 OS 來命名的)

PATH 更新後,執行如下:

./build.sh -m evbarm -u kernel=SMDK2410_INSTALL

它就會編譯 SMDK2410 的 kernel 了。

假如出現找不到 Compiler Tools 的情況時,我們可以用較複雜的參數來編譯,
自行指定 Compiler 路徑,如下:
./build.sh -U -u -m evbarm -O /home/2410/netbsd/obj -T /usr/local/arm/netbsd -D /home/2410/netbsd/build -R /home/2410/netbsd/release kernel=SMDK2410_INSTALL

而 kernel 內容的修改和之前 FreeBSD 類似,連目錄結構都很相似,
它是放在
sys/arch/evbarm/conf/SMDK2410

對照以前 FreeBSD 的 kernel 路徑
/usr/src/sys/i386/conf/GENERIC

而這次的則是
/usr/src/sys/arch/evbarm/conf/SMDK2410

真的是很相似,很有 BSD 的味道。

參考文件是:
製作嵌入式晶片s3c2410板卡的NetBSD啟動鏡像

5a.以 NFS rootfs 方式開機進入

NFS rootfs 大概是最方便的作法了,這邊指的方便,指的是方便開發 application,
還有方便修改執行檔之類的動作。

不過在 NetBSD 上,動作流程比 Linux 麻煩許多,
最討厭是竟然要動到 DHCP Server,以下是流程:

NFS and DHCP Howto
1.重點,設定 DHCP Server 如下指定:
host my2410.home {
hardware ethernet 00:0a:b1:00:01:ff;
fixed-address 192.168.1.100;
next-server 192.168.1.18;
option root-path "/home/nfsroot/root";
}


網卡卡號在 NetBSD 開機時會顯示,如下:
cs0 at ssextio0 addr 0x18000000 intr 9
cs0: CS8900 rev. K, address 00:0a:b1:00:01:ff, media UTP


next-server 很重要,它表示了 NFS Server 的 IP,
option root-path 也很重要,它表示 NFS Server 上 rootfs 的路徑

2.NFS設定如下:
/home/nfsroot/root 192.168.1.0/255.255.255.0(rw,no_root_squash,sync)
/home/nfsroot/swap 192.168.1.0/255.255.255.0(rw,no_root_squash,sync)


rootfs 和 swap 要分開設,原因目前不清楚,按照 ko 設定的。

swap 建立方法如下:
dd if=/dev/zero of=swap bs=4k count=8k

3.NetBSD 設定如下:
etc/myname
my2410

etc/mygate
192.168.1.3

etc/rc.conf
rc_configured=YES

# Add local overrides below
#
nfs_client=YES
wscons=YES
sshd=NO
sendmail=NO

etc/hosts
192.168.1.100 my2410
192.168.1.18 coDebian

etc/fstab
192.168.1.18:/home/nfsroot/root / nfs rw 0 0
kernfs /kern kernfs rw
procfs /proc procfs rw,noauto
192.168.1.18:/home/nfsroot/swap none swap sw,nfsmntpt=/swap

4.建立 kern 和 proc 目錄
mkdir kern proc

5.NetBSD kernel
不要用 SMDK2410_INSTALL

修改 SMDK2410 後,直接使用 SMDK2410 來編譯 kernel
SMDK2410_INSTALL 內主要設定的,就是用 RAM Disk 時的設定

SMDK2410 要改的不多,如下:
config netbsd root on ? type ?

改成
config netbsd root on ? type nfs

6.編譯成功後,不需要之前的 RAM Disk 一堆步驟,直接用 netbsd.bin 即可。

以下是第一次成功畫面:
SMDK2410 # nfs 0x30200000 192.168.1.18:/home/2410/netbsd/netbsd.bin;go 30200000
File transfer via NFS from server 192.168.1.18; our IP address is 192.168.1.100
Filename '/home/2410/netbsd/netbsd.bin'.
Load address: 0x30200000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#####################################################
done
Bytes transferred = 2597192 (27a148 hex)
## Starting application at 0x30200000 ...
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 3.0.1 (SMDK2410) #1: Fri Sep 29 07:36:19 UTC 2006
root@coDebian:/home/2410/netbsd/obj/sys/arch/evbarm/compile/SMDK2410
total memory = 65536 KB
avail memory = 58680 KB
mainbus0 (root)
cpu0 at mainbus0: ARM920T rev 0 (ARM9TDMI core)
cpu0: DC enabled IC enabled WB enabled EABT
cpu0: 16KB/32B 64-way Instruction cache
cpu0: 16KB/32B 64-way write-back-locking-A Data cache
ssio0 at mainbus0: fclk 200 MHz hclk 100 MHz pclk 50 MHz
ohci0 at ssio0 intr 26
ohci0: OHCI version 1.0
usb0 at ohci0: USB revision 1.0
uhub0 at usb0
uhub0: Samsung OHCI root hub, class 9/0, rev 1.00/1.00, addr 1
uhub0: 2 ports with 2 removable, self powered
sscom0 at ssio0 unit 0: UART0 addr=50000000
sscom0: console (major=104)
sscom1 at ssio0 unit 1: UART1 addr=50004000
ssextio0 at ssio0
cs0 at ssextio0 addr 0x18000000 intr 9
cs0: CS8900 rev. K, address 00:0a:b1:00:01:ff, media UTP
lcd0 at ssio0
wsdisplay0 at lcd0 kbdmux 1
wsmux1: connecting to wsdisplay0
ssspi1 at ssio0 unit 1
sskbd0 at ssspi1 intr 1
wskbd0 at sskbd0 mux 1
wskbd0: connecting to wsdisplay0
clock: hz=100 stathz = 64 PCLK=50000000 prescaler=2 tc=24414
boot device:
root on cs0
nfs_boot: trying DHCP/BOOTP
cs0: failed to enable memory mode
nfs_boot: DHCP next-server: 192.168.1.18
nfs_boot: my_domain=home
nfs_boot: my_addr=192.168.1.100
nfs_boot: my_mask=255.255.255.0
nfs_boot: gateway=192.168.1.3
root on 192.168.1.18:/home/nfsroot/root
warning: no /dev/console
init: Creating mfs /dev (409 blocks, 1024 inodes)
Fri Sep 29 07:43:12 UTC 2006
Checking for botched superblock upgrades: done.
Starting file system checks:
Setting tty flags.
Setting sysctl variables:
Starting network.
Hostname: myname
IPv6 mode: host
Configuring network interfaces:.
add net default: gateway 192.168.1.3
Building databases...
wsdisplay0: screen 1 added (30x32bpp8, vt100 emulation)
wsdisplay0: screen 2 added (30x32bpp8, vt100 emulation)
wsdisplay0: screen 3 added (30x32bpp8, vt100 emulation)
wsdisplay0: screen 4 added (30x32bpp8, vt100 emulation)
Starting syslogd.
Checking for core dump...
savecore: /netbsd: kvm_openfiles: /netbsd: No such file or directory
Sep 29 07:43:22 myname savecore: /netbsd: kvm_openfiles: /netbsd: No such file or directory
Mounting all filesystems...
mount: realpath /kern: No such file or directory
Clearing /tmp.
Creating a.out runtime link editor directory cache.
Checking quotas: done.
Setting securelevel: kern.securelevel: 0 -> 1
mount_nfs: realpath /swap: No such file or directory
swapctl: 192.168.1.18:/home/nfsroot/swap: mount failed
/etc/rc: WARNING: No swap space configured!
Starting virecover.
Starting local daemons:.
Updating motd.
Starting inetd.
Starting cron.
Fri Sep 29 07:43:30 UTC 2006



NetBSD/evbarm (myname) (console)

login: root
Sep 29 07:43:36 myname login: ROOT LOGIN (root) ON console
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 3.0.1 (SMDK2410) #1: Fri Sep 29 07:36:19 UTC 2006

Welcome to NetBSD!

Terminal type is vt100.
We recommend creating a non-root account and using su(1) for root access.
myname#


5b.使用 RAM rootfs 方式在本機載入

1.以 NFS rootfs 成功的版本進行修改,修改下面幾個檔案:

etc/rc.conf
rc_configured=YES
wscons=YES
sshd=NO
sendmail=NO
no_swap=YES
swapoff=YES



etc/fstab
/dev/md0a / ffs rw 1 1
kernfs /kern kernfs rw
procfs /proc procfs rw,noauto


2.修改 /usr/src/sys/arch/evbarm/conf/SMDK2410


config netbsd root on ? type nfs

改回
config netbsd root on ? type ?

3.修改進入 multi-user mode
要進入 multi-user mode,有幾個項目:

1. rc.conf 內的 rc_configured 要設為 YES
2.在 RAM rootfs 模式時,SMDK2410_INSTALL 要修改,如下:

sys/arch/evbarm/conf/SMDK2410_INSTALL
#options BOOTHOWTO=RB_SINGLE

要改為
options BOOTHOWTO=0


至於
sys/arch/evbarm/conf/INSTALL


MEMORY_RBFLAGS=0x00

可以不需要設定,我懷疑這個設定在 BOOTHOWTO=0 幫你設了。

4.建立 image 檔案
NetBSD 的 kernel 和 rootfs 是綁在一起的,要在 kernel 當中先設定好 rootfs 的大小,如下:
sys/arch/evbarm/conf/INSTALL
options MEMORY_DISK_ROOT_SIZE=6510

改為
options MEMORY_DISK_ROOT_SIZE=49152

之後按照下面的步驟建立 image 檔案:

要建立 image.fs 這樣的 RAM Disk 影像檔,指令如下:
nbmakefs -s 24m -t ffs image_24m.fs rootfs

-s 影像檔大小
-t 影像檔檔案系統格式(只有 ffs 可以用)
image_24m.fs 目的影像檔檔名
rootfs 來源目錄
=========================================

http://www.bsdnewsletter.com/2003/09/Features102.html

要將 kernel 和 rootfs 合併,動作如下:
cp sys/arch/evbarm/compile/obj/SMDK2410_INSTALL/netbsd .
arm--netbsdelf-mdsetimage -sv netbsd image.fs
arm--netbsdelf-objcopy -S -O binary netbsd netbsd.bin

6.透過 u-boot 載入
最後要載到板子上,要使用如下參數來下載啟動:

啟動 NetBSD 語法如下:
tftp 30200000 netbsd.bin; go 30200000

也可以用 NFS 方式載入,如下:
nfs 0x30200000 192.168.1.18:/home/2410/netbsd/netbsd.bin;go 0x30200000

備註:
關於 dev/ 的裝置,可能會出現警告的訊息,目前不清楚 dev/ 的裝置是不是必要的,
而要建立 dev 的裝置方法很簡單~~

要建立 dev 的裝置,NetBSD 很貼心的提供了 MAKEDEV 的 script 來幫忙建立,
可以依據不同類別來建立,目前類別有下列這些:
default
floppy
init
local
ramdisk
std
usbs
wscons

另外還有一個類別是
all

all 類別包含全部的裝置檔。

因此要建立,是很簡單的,在 NetBSD 下只要執行:
./MAKEDEV ramdisk

而前面我們編譯過的 Compiler Tools 裡面有包含了 mknod,它改名叫做 nbmknod,
因此在其他平台要使用它,則要執行:
./MAKEDEV -m /usr/local/arm/netbsd/bin/nbmknod ramdisk

-m mknod 的呼叫檔名和完整路徑

要編譯 evbarm 的檔案時,我們知道有
nbmake

可以使用,但是就算用 nbmake,經常會碰到環境變數的問題,
其實 NetBSD 已經幫我們想到了,可以直接用
nbmake-evbarm

它只是個 script 的檔案,裡面就只是設定一些環境變數,之後就去呼叫 nbmake,非常的方便~~

(2006-10-06)
小型化 rootfs 製作手記:

busybox 在 Embedded Linux 上很有名,它將 Linux 上常見的 tools 進行打包,讓 tools 的體積大幅縮小,
它用的技巧很簡單而有效率,方法是:

我們知道 application 有 靜態編譯 和 動態編譯 兩種,
靜態編譯是把 library 編譯後放入特定目錄,像是 /lib,
需要用到的 application,會在使用時自己去 /lib 下面找 library,
動態編譯則是把 library 和 application 編譯在一起,
這樣的好處是 application 在執行的時候,不需要去特定的目錄搜尋 library,
因此只要是同一個平台的程式,直接 copy application 檔案過去即可使用,
不需要再找一堆 library 並一個一個複製過去~~
可是靜態編譯的缺點是檔案多半都很大,隨便一個 application 檔案,都會需要到好幾 MB。

busybox 這類的程式則是採取了折衷的辦法,我們先將需要的 application 進行選取,
之後 busybox 再編譯這些 application,以「靜態編譯」的方式將它們編譯成「一個執行檔」,
這樣的結果是,許多用同一個 library 的 application,它們的 library 只會放一份在「這個執行檔」中,
有類似動態編譯時,所有 application 都到 /lib 找 library 的味道,
但是又能做到「靜態編譯」的優點,只需要一個執行檔,就能夠在相同平台直接執行使用,不需要另外找 library,
減少了移植的麻煩,也減少了 code size。

在 BSD 當中,沒有 busybox,busybox 也不支援 BSD,不過 BSD 有 crunchgen,
crunchgen 的原理和 busybox 相同,不同的地方在於,
他的設定檔需要自行編寫,之後透過它產生一個制式化的 Makefile,
接著 make 出來的檔案,就會有和 busybox 一樣風格的「執行檔」,
crunchgen 我們可以說他是 busybox 的手動版,但正因如此,它多了很大的彈性~~

下面動作我是參考
http://www.bsdnewsletter.com/2003/09/Features102b.html

的說明,加上自己的測試使用後得出的步驟、方法、技巧:

首先,我先把整個流程、步驟先寫上,之後在對細節做些說明:
1.編寫 mytiny.conf (檔名可自訂,但下面所有 mytiny 都需要改成自己的檔名),下面是我依照網站內容編寫:
srcdirs /home/2410/netbsd/usr/src/bin /home/2410/netbsd/usr/src/sbin /home/2410/netbsd/usr/src/usr.bin /home/2410/netbsd/usr/src/usr.sbin /home/2410/netbsd/usr/src/libexec

progs pwd_mkdb passwd login init sh mount_ffs mount_kernfs mount_procfs mount newfs ls reboot mount_nfs ttyflags getty

ln sh -sh
ln newfs mount_mfs

libs -lutil -lcrypt -ledit -ltermcap -ll


2.執行如下:
cd /home/2410/netbsd/usr/mytiny
nbcrunchgen -m Makefile mytiny.conf
nbmake-evbarm -f Makefile objs exe


3.要重新編譯的時候,執行如下:
cd /home/2410/netbsd/usr/mytiny
nbmake-evbarm clean
rm mytiny.c mytiny.cache Makefile
vi /home/2410/netbsd/usr/mytiny/mytiny.conf(編輯設定檔)
nbcrunchgen -m Makefile mytiny.conf
nbmake-evbarm -f Makefile objs exe


4.執行時,我們會發現出現錯誤,要修改這幾個檔案:
/home/2410/netbsd/usr/src/usr.bin/passwd/Makefile

# $NetBSD: Makefile,v 1.40 2005/03/04 20:41:09 he Exp $
# from: @(#)Makefile 8.3 (Berkeley) 4/2/94

.include

PROG= passwd
SRCS= local_passwd.c passwd.c
MAN= passwd.1

CPPFLAGS+=-I${.CURDIR} -DLOGIN_CAP

DPADD+= ${LIBCRYPT} ${LIBUTIL}
LDADD+= -lcrypt -lutil

BINOWN= root
BINMODE=4555

.include


/home/2410/netbsd/usr/src/usr.bin/login/Makefile
# $NetBSD: Makefile,v 1.45 2005/03/04 20:41:09 he Exp $
# @(#)Makefile 8.1 (Berkeley) 7/19/93

.include

WARNS= 2
PROG= login
SRCS= copyrightstr.c
DPADD+= ${LIBUTIL} ${LIBCRYPT}
LDADD+= -lutil -lcrypt
BINOWN= root
BINMODE=4555

SRCS+= login.c
CPPFLAGS+=-DLOGIN_CAP -DSUPPORT_UTMP -DSUPPORT_UTMPX

CLEANFILES+= copyrightstr.c

copyrightstr.c: ${NETBSDSRCDIR}/sys/conf/copyright
${_MKTARGET_CREATE}
rm -f ${.TARGET}
awk '\
BEGIN { print "const char copyrightstr[] =" }\
{ print "\""$$0"\\n\""}\
END { print "\"\\n\";" }\
' ${.ALLSRC} > ${.TARGET}

.include


5.順利編譯之後,便會產生 mytiny 的執行檔。

問題與說明:

Q:crunchgen 檔案在哪裡?
A:
NetBSD 真的很方便,它已經將 Compiler Tools 很完整的準備好了,像 crunchgen 這樣的工具也一併提供了,
此外,它還依據平台將它們重新命名,以 evbarm 來說,所有工具前面都會冠上 nb 字頭,
crunchgen 就更名為 nbcrunchgen,
make 就更名為 nbmake,
此外,前面提到過了,它還很貼心的提供了 nbmake-evbarm 這樣的 script,
差別在於會先設定好環境變數,接著呼叫 nbmake 執行。

而以我來說,nbcrunchgen 會放在前面提過的目錄,以我來說就是 /usr/local/arm/netbsd/bin/


Q:要怎麼查詢 library?mytiny.conf 裡面需要指定 libs 哩~~
A:
查詢方法有兩種,而且以第二種較確實。

第一種:
在 ARM 板子上,使用 ldd 查詢,指令如下:
ldd /bin/sh /bin/ls

可以指定多個指令,會全部列出~~

第二種:
第一種方法雖然可以列出執行檔所需的 library,可是按它的要求修改,有時候好像還是不行耶,怎麼辦?
我們這時候可以直接去看該指令(執行檔)的 source code 目錄下的 Makefile,
以 /bin/sh 來說,它的目錄會是在 usr/src/bin/sh/,這時去看它的 Makefile(usr/src/bin/sh/Makefile),
看到如下內容:
......
LDADD+= -ll -ledit -ltermcap
......


sh 需要的 library 就是 -ll -ledit -ltermcap 這幾個~~~

其他的執行檔搜尋方式雷同,而需要的 library 在 mytiny.conf 中只需要列一次,不需要重複列出~~

另外要注意的是,當出現下面的錯誤時,就是有缺 library:
/usr/local/arm/netbsd/bin/arm--netbsdelf-gcc -Wl,-nostdlib -static -o mytiny -Wl,-rpath-link,/home/2410/netbsd/build/lib:/home/2410/netbsd/build/usr/lib -L/home/2410/netbsd/build/lib -B/home/2410/netbsd/build/usr/lib/ -B/home/2410/netbsd/build/usr/lib/ mytiny.o pwd_mkdb.cro passwd.cro login.cro init.cro sh.cro mount_ffs.cro mount_kernfs.cro mount_procfs.cro mount.cro newfs.cro ls.cro reboot.cro mount_nfs.cro ttyflags.cro getty.cro -lutil -ledit -ltermcap -ll -L/home/2410/netbsd/build/usr/lib -L/home/2410/netbsd/build/usr/lib
passwd.cro(.text+0x54): In function `$a':
: undefined reference to `crypt'
passwd.cro(.text+0x1e4): In function `$a':
: undefined reference to `pw_gensalt'
passwd.cro(.text+0x210): In function `$a':
: undefined reference to `crypt'
login.cro(.text+0x54c): In function `$a':
: undefined reference to `crypt'
init.cro(.text+0x770): In function `single_user$$from$$init':
: undefined reference to `crypt'
collect2: ld returned 1 exit status


以這個為例,就是 passwd 這個執行檔編譯沒過,它還說 crypt 沒有定義,
此時可以以 grep 的方式搜尋 crypt,看看是什麼 lib 有包含 crypt 的定義,
便可發現,可能是 -lcrypt 缺了~~

Q:為何要修改 passwd 和 login 的 Makefile?
A:
在編譯時,一直發生錯誤,而且錯誤都出在 passwd 或 login 裡面,
此時看看它們的 Makefile,發現頗複雜,主要是它提供了參數來讓你設定,
類似如下:
BINMODE=4555

.if (${USE_KERBEROS} != "no")
CPPFLAGS+= -DKERBEROS5 -I${DESTDIR}/usr/include/krb5
SRCS+= krb5_passwd.c

DPADD+= ${LIBKRB5} ${LIBCRYPTO} ${LIBASN1} ${LIBCOM_ERR} ${LIBROKEN} ${LIBCRYPT}
LDADD+= -lkrb5 -lcrypto -lasn1 -lcom_err -lroken -lcrypt
LINKS+= ${BINDIR}/passwd ${BINDIR}/kpasswd
MAN+= kpasswd.1
.endif

.if (${USE_PAM} != "no")
CPPFLAGS+=-DUSE_PAM
SRCS+= pam_passwd.c
LDADD+=-lpam ${PAM_STATIC_LDADD}
DPADD+=${LIBPAM} ${PAM_STATIC_DPADD}
.endif

.include


我們知道 PAM 我們並不需要,而且加了,增加了許多 code 也增加了其他 library 造成檔案更大,
而目前,我還不會加入參數來將它略過,因此我使用較為土法煉鋼的方式,
將這段 code 直接拿掉~~~

因此整個 code 拿光了,變成如下:
# $NetBSD: Makefile,v 1.40 2005/03/04 20:41:09 he Exp $
# from: @(#)Makefile 8.3 (Berkeley) 4/2/94

.include

PROG= passwd
SRCS= local_passwd.c passwd.c
MAN= passwd.1

CPPFLAGS+=-I${.CURDIR} -DLOGIN_CAP

DPADD+= ${LIBCRYPT} ${LIBUTIL}
LDADD+= -lcrypt -lutil

BINOWN= root
BINMODE=4555

.include


要拿掉的部份,就是看 .if 和 .endif,像 HTML 那樣成對的拿掉~~~

Q:要如何使用?
A:
最後要用,依網站所述即可,作法類似如下:
mkdir /home/nfsroot/sbin
mkdir /home/nfsroot/bin
......
cp mytiny /home/nfsroot/root/sbin/init
ln /home/nfsroot/root/sbin/init /home/nfsroot/root/bin/sh
ln /home/nfsroot/root/sbin/init /home/nfsroot/root/bin/ls
......

這邊注意一點,我們直接用 ln 不加任何參數即可,
ln 不加任何參數,則 link 出來的檔案,每個都沒有實體,
都會指向到 init,所以每個檔案大小都相同,
而且有趣的是,當 init 更新之後,所有檔案也都會更新(因為沒有實體),
檔案大小都會是新 init 的 size。

Q:要如何更改 passwd 內容或 root 密碼?
A:
要變更 passwd 我是參考
http://web.bsdlab.idv.tw/FreeBSD_CVSup_Source.htm

其實關鍵在於如何使用 pwd_mkdb,而以我的環境來說,作法如下:

1.修改 passwd
vi /home/nfsroot/root/etc/passwd

2.修改 master.passwd
vi /home/nfsroot/root/etc/master.passwd

3.使用 pwd_mkdb
cd /home/nfsroot/root/etc
nbpwd_mkdb -p -d /home/nfsroot/root ./master.passwd

2 則留言:

amy 提到...

您好:
今日找一些上課資料偶發現您的部落格,可以請教您"BNF"表示法的問題嗎??
因為真的解不出來!!!!如下

sum=0;
for i=1 to 100
sum=sum+I;

以上翻成BNF語法表示

Cody 提到...

麻煩您,作業請自己上google找答案!