大樹底下好乘涼 ︰ 《歷史觀》

220px-TheHandmaidsTale(1stEd)
有名萬物之母

使女的故事》 The handmaid’s tale 是加拿大女性作家瑪格麗特‧愛特伍 Margaret Atwood 所寫的小說,受歐美文學界推崇不已的作品,已被列入重要經典作品中。

□︰數位的發展導致了一種疑慮,未來未必能『解碼』過去,那麼今天的存在,或許就成了『未知』的世紀??

○︰假使不必為『古人』擔憂!那又何必為『來者』遺憾?

即使將有『計算歷史學家』,或許也會遇到『可計算性問題』,可能不免『量子不確定性原理』,所謂的『當下』只在『前後』之『』的吧!!

每一台 PC 主機板上都有一個『BIOS 』 Basic Input Output System 掌管開機動作。這個『第一啟動』韌體一直隱藏在『保密合約』 NDA  non-disclosure agreement 幕後。曾經 Linux Bios 計畫努力於打開黑箱,直到今天稱之為 coreboot 。在那個應許的年代,已走入歷史的『 SUN Microsystems 』之『 Open Bios 』計畫裡的『 open firmware 』架構,就是『設備樹』的原點︰

IEEE Std 1275-1994
IEEE Standard for Boot (Initialization Configuration) Firmware: Core Requirements and Practices
……
3.2 Device tree
The device tree is a hierarchical data structure that describes the system hardware, describes user configuration choices, contains firmware device drivers for hardware devices, and contains support routines for use by those drivers.

The device tree’s structure mimics the organization of the system hardware, viewed as a hierarchy of interconnected buses and their attached devices. The device tree consists of a set of device nodes that are interconnected to form a tree. An individual device node
represents either a hardware bus, a hardware device, or a set of interrelated software procedures. ……

二零零八年起 Power.org^{TM} Standard for Embedded Power Architecture^{TM} Platform Requirements (ePAPR) 開始推廣 open firmware 架構︰
……
1.2 Relationship to IEEETM 1275

The ePAPR is loosely related to the IEEE 1275 Open Firmware standard—IEEE Standard for Boot (Initialization Configuration) Firmware: Core Requirements and Practices [2].
The original IEEE 1275 specification and its derivatives such as CHRP [10] and PAPR [16] address problems of general purpose computers, such as how a single version of an operating system can work on several different computers within the same family and the problem of loading an operating system from user-installed I/O devices. ……

晏子春秋‧內篇雜下第六

晏子將至楚,楚聞之,謂左右曰:晏嬰,齊之習辭者也,今方來,吾欲辱之,何以也?

左右對曰:為其來也,臣請縛一人,過王而行,王曰:『何為者也?』對曰:『齊人也.』王曰:『何坐?』曰:『坐盜.』

晏子至,楚王賜晏子酒,酒酣,吏二縛一人詣王,王曰:縛者曷為者也?對曰:齊人也,坐盜.

王視晏子曰:齊人固善盜乎?

晏子避席對曰:嬰聞之,橘生淮南則為橘,生于淮北則為枳,葉徒相似,其實味不同.所以然者何?水土異也.今民生長于齊不盜,入楚則盜,得無楚之水土使民善盜耶?

王笑曰:聖人非所與熙也,寡人反取病焉.

200px-Madarines_white_bg

南橘

200px-Poncirus_trifoliata_Prague_2011_1

北枳

果真一方水土,一方人物,這個『設備樹』到了『樹莓派』手上,又有一番風情;別樣『架構』  skeleton.dtsi ︰

# Linux/arch/arm/boot/dts/skeleton.dtsi

/*
 * Skeleton device tree; the bare minimum needed to boot; just include and
 * add a compatible value.  The bootloader will typically populate the memory
 * node.
*/
 
/ {
        #address-cells = <1>;
        #size-cells = <1>;
        chosen { };
        aliases { };
        memory { device_type = "memory"; reg = <0 0>; };
};

就讓我們比較 bcm2709-rpi-2-b.dts + bcm2709.dtsi + skeleton.dtsi 之原始檔和解碼過的 bcm2709-rpi-2-b.dtb 看看異同︰

# 解碼 dtb
dtc -I dtb -O dts -o bcm2709-rpi-2-b.dts.decode /boot/bcm2709-rpi-2-b.dtb

/dts-v1/;

/ {
	#address-cells = <0x1>;
	#size-cells = <0x1>;
	compatible = "brcm,bcm2709";
	model = "Raspberry Pi 2 Model B";
	interrupt-parent = <0x1>;

	chosen {
		bootargs = [00];
	};

	aliases {
		soc = "/soc";
		spi0 = "/soc/spi@7e204000";
		i2c0 = "/soc/i2c@7e205000";
		i2c1 = "/soc/i2c@7e804000";
		i2s = "/soc/i2s@7e203000";
		gpio = "/soc/gpio";
		intc = "/soc/interrupt-controller";
		leds = "/soc/leds";
		sound = "/sound";
	};

	memory {
		device_type = "memory";
		reg = <0x0 0x0>;
	};

	soc {
		compatible = "simple-bus";
		#address-cells = <0x1>;
		#size-cells = <0x1>;
		ranges = <0x7e000000 0x3f000000 0x1000000>;
		linux,phandle = <0x13>;
		phandle = <0x13>;

		interrupt-controller {
			compatible = "brcm,bcm2708-armctrl-ic";
			reg = <0x7e00b200 0x200>;
			interrupt-controller;
			#interrupt-cells = <0x2>;
			linux,phandle = <0x1>;
			phandle = <0x1>;
		};

		gpio {
			compatible = "brcm,bcm2835-gpio";
			reg = <0x7e200000 0xb4>;
			interrupts = <0x2 0x11 0x2 0x12>;
			gpio-controller;
			#gpio-cells = <0x2>;
			interrupt-controller;
			#interrupt-cells = <0x2>;
			linux,phandle = <0x8>;
			phandle = <0x8>;

			spi0_pins {
				brcm,pins = <0x7 0x8 0x9 0xa 0xb>;
				brcm,function = <0x4>;
				linux,phandle = <0x4>;
				phandle = <0x4>;
			};

			i2c0 {
				brcm,pins = <0x0 0x1>;
				brcm,function = <0x4>;
				linux,phandle = <0x6>;
				phandle = <0x6>;
			};

			i2c1 {
				brcm,pins = <0x2 0x3>;
				brcm,function = <0x4>;
				linux,phandle = <0x7>;
				phandle = <0x7>;
			};

			i2s {
				brcm,pins = <0x12 0x13 0x14 0x15>;
				brcm,function = <0x4>;
				linux,phandle = <0x2>;
				phandle = <0x2>;
			};
		};

		i2s@7e203000 {
			compatible = "brcm,bcm2708-i2s";
			reg = <0x7e203000 0x20 0x7e101098 0x2>;
			dma-names = "tx", "rx";
			status = "disabled";
			#sound-dai-cells = <0x0>;
			pinctrl-names = "default";
			pinctrl-0 = <0x2>;
			linux,phandle = <0xd>;
			phandle = <0xd>;
		};

		spi@7e204000 {
			compatible = "brcm,bcm2708-spi";
			reg = <0x7e204000 0x1000>;
			interrupts = <0x2 0x16>;
			clocks = <0x3>;
			#address-cells = <0x1>;
			#size-cells = <0x0>;
			status = "disabled";
			pinctrl-names = "default";
			pinctrl-0 = <0x4>;
			linux,phandle = <0xe>;
			phandle = <0xe>;

			spidev@0 {
				compatible = "spidev";
				reg = <0x0>;
				#address-cells = <0x1>;
				#size-cells = <0x0>;
				spi-max-frequency = <0x7a120>;
			};

			spidev@1 {
				compatible = "spidev";
				reg = <0x1>;
				#address-cells = <0x1>;
				#size-cells = <0x0>;
				spi-max-frequency = <0x7a120>;
			};
		};

		i2c@7e205000 {
			compatible = "brcm,bcm2708-i2c";
			reg = <0x7e205000 0x1000>;
			interrupts = <0x2 0x15>;
			clocks = <0x5>;
			#address-cells = <0x1>;
			#size-cells = <0x0>;
			status = "disabled";
			pinctrl-names = "default";
			pinctrl-0 = <0x6>;
			clock-frequency = <0x186a0>;
			linux,phandle = <0xf>;
			phandle = <0xf>;
		};

		i2c@7e804000 {
			compatible = "brcm,bcm2708-i2c";
			reg = <0x7e804000 0x1000>;
			interrupts = <0x2 0x15>;
			clocks = <0x5>;
			#address-cells = <0x1>;
			#size-cells = <0x0>;
			status = "disabled";
			pinctrl-names = "default";
			pinctrl-0 = <0x7>;
			clock-frequency = <0x186a0>;
			linux,phandle = <0x10>;
			phandle = <0x10>;
		};

		leds {
			compatible = "gpio-leds";
			linux,phandle = <0x14>;
			phandle = <0x14>;

			act {
				label = "led0";
				linux,default-trigger = "mmc0";
				gpios = <0x8 0x2f 0x0>;
				linux,phandle = <0x11>;
				phandle = <0x11>;
			};

			pwr {
				label = "led1";
				linux,default-trigger = "input";
				gpios = <0x8 0x23 0x0>;
				linux,phandle = <0x12>;
				phandle = <0x12>;
			};
		};
	};

	clocks {
		compatible = "simple-bus";
		#address-cells = <0x1>;
		#size-cells = <0x0>;

		i2c {
			compatible = "fixed-clock";
			reg = <0x1>;
			#clock-cells = <0x0>;
			clock-frequency = <0xee6b280>;
			linux,phandle = <0x5>;
			phandle = <0x5>;
		};

		clock@2 {
			compatible = "fixed-clock";
			reg = <0x2>;
			#clock-cells = <0x0>;
			clock-output-names = "spi";
			clock-frequency = <0xee6b280>;
			linux,phandle = <0x3>;
			phandle = <0x3>;
		};
	};

	timer {
		compatible = "arm,armv7-timer";
		clock-frequency = <0x124f800>;
		interrupts = <0x3 0x0 0x3 0x1 0x3 0x3 0x3 0x2>;
		always-on;
	};

	cpus {
		#address-cells = <0x1>;
		#size-cells = <0x0>;
		linux,phandle = <0x15>;
		phandle = <0x15>;

		cpu@0 {
			device_type = "cpu";
			compatible = "arm,cortex-a7";
			reg = <0xf00>;
			clock-frequency = <0x2faf0800>;
			linux,phandle = <0x9>;
			phandle = <0x9>;
		};

		cpu@1 {
			device_type = "cpu";
			compatible = "arm,cortex-a7";
			reg = <0xf01>;
			clock-frequency = <0x2faf0800>;
			linux,phandle = <0xa>;
			phandle = <0xa>;
		};

		cpu@2 {
			device_type = "cpu";
			compatible = "arm,cortex-a7";
			reg = <0xf02>;
			clock-frequency = <0x2faf0800>;
			linux,phandle = <0xb>;
			phandle = <0xb>;
		};

		cpu@3 {
			device_type = "cpu";
			compatible = "arm,cortex-a7";
			reg = <0xf03>;
			clock-frequency = <0x2faf0800>;
			linux,phandle = <0xc>;
			phandle = <0xc>;
		};
	};

	__overrides__ {
		arm_freq = "", "", "", "\tclock-frequency:0", "", "", "", "\nclo
ck-frequency:0", "", "", "", "\vclock-frequency:0", "", "", "", "\fclock-frequen
cy:0";
		i2s = "", "", "", "\rstatus";
		spi = [00 00 00 0e 73 74 61 74 75 73 00];
		i2c0 = [00 00 00 0f 73 74 61 74 75 73 00];
		i2c1 = [00 00 00 10 73 74 61 74 75 73 00];
		i2c0_baudrate = [00 00 00 0f 63 6c 6f 63 6b 2d 66 72 65 71 75 65
	};

	__symbols__ {
		soc = "/soc";
		intc = "/soc/interrupt-controller";
		gpio = "/soc/gpio";
		spi0_pins = "/soc/gpio/spi0_pins";
		i2c0_pins = "/soc/gpio/i2c0";
		i2c1_pins = "/soc/gpio/i2c1";
		i2s_pins = "/soc/gpio/i2s";
		i2s = "/soc/i2s@7e203000";
		spi0 = "/soc/spi@7e204000";
		i2c0 = "/soc/i2c@7e205000";
		i2c1 = "/soc/i2c@7e804000";
		leds = "/soc/leds";
		act_led = "/soc/leds/act";
		pwr_led = "/soc/leds/pwr";
		clk_i2c = "/clocks/i2c";
		clk_spi = "/clocks/clock@2";
		cpus = "/cpus";
		v7_cpu0 = "/cpus/cpu@0";
		v7_cpu1 = "/cpus/cpu@1";
		v7_cpu2 = "/cpus/cpu@2";
		v7_cpu3 = "/cpus/cpu@3";
		sound = "/sound";
	};
};