diff --git a/examples/hifive-unmatched-a00.dts b/examples/hifive-unmatched-a00.dts new file mode 100644 index 0000000..e127454 --- /dev/null +++ b/examples/hifive-unmatched-a00.dts @@ -0,0 +1,655 @@ +/dts-v1/; + +/ { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000", "sifive,fu740"; + model = "SiFive HiFive Unmatched A00"; + + aliases { + serial0 = "/soc/serial@10010000"; + serial1 = "/soc/serial@10011000"; + ethernet0 = "/soc/ethernet@10090000"; + spi0 = "/soc/spi@10050000"; + }; + + chosen { + stdout-path = "serial0"; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + timebase-frequency = <0xf4240>; + assigned-clocks = <0x01 0x00>; + assigned-clock-rates = <0x47868c00>; + u-boot,dm-spl; + + cpu@0 { + compatible = "sifive,bullet0", "riscv"; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x4000>; + next-level-cache = <0x02>; + reg = <0x00>; + riscv,isa = "rv64imac"; + status = "okay"; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x03>; + }; + }; + + cpu@1 { + compatible = "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x02>; + reg = <0x01>; + riscv,isa = "rv64imafdc"; + tlb-split; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x04>; + }; + }; + + cpu@2 { + compatible = "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x02>; + reg = <0x02>; + riscv,isa = "rv64imafdc"; + tlb-split; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x05>; + }; + }; + + cpu@3 { + compatible = "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x02>; + reg = <0x03>; + riscv,isa = "rv64imafdc"; + tlb-split; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x06>; + }; + }; + + cpu@4 { + compatible = "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x02>; + reg = <0x04>; + riscv,isa = "rv64imafdc"; + tlb-split; + clocks = <0x01 0x00>; + u-boot,dm-spl; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + u-boot,dm-spl; + phandle = <0x07>; + }; + }; + }; + + soc { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "sifive,fu740-c000", "sifive,fu740", "simple-bus"; + ranges; + u-boot,dm-spl; + + interrupt-controller@c000000 { + #interrupt-cells = <0x01>; + compatible = "sifive,plic-1.0.0"; + reg = <0x00 0xc000000 0x00 0x4000000>; + riscv,ndev = <0x45>; + interrupt-controller; + interrupts-extended = <0x03 0xffffffff 0x04 0xffffffff 0x04 0x09 0x05 0xffffffff 0x05 0x09 0x06 0xffffffff 0x06 0x09 0x07 0xffffffff 0x07 0x09>; + phandle = <0x0a>; + }; + + clock-controller@10000000 { + compatible = "sifive,fu740-c000-prci"; + reg = <0x00 0x10000000 0x00 0x1000>; + clocks = <0x08 0x09>; + #clock-cells = <0x01>; + #reset-cells = <0x01>; + resets = <0x01 0x00 0x01 0x01 0x01 0x02 0x01 0x03 0x01 0x05 0x01 0x06>; + reset-names = "ddr_ctrl", "ddr_axi", "ddr_ahb", "ddr_phy", "gemgxl_reset", "cltx_reset"; + u-boot,dm-spl; + phandle = <0x01>; + }; + + serial@10010000 { + compatible = "sifive,fu740-c000-uart", "sifive,uart0"; + reg = <0x00 0x10010000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x27>; + clocks = <0x01 0x07>; + status = "okay"; + u-boot,dm-spl; + }; + + serial@10011000 { + compatible = "sifive,fu740-c000-uart", "sifive,uart0"; + reg = <0x00 0x10011000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x28>; + clocks = <0x01 0x07>; + status = "okay"; + }; + + i2c@10030000 { + compatible = "sifive,fu740-c000-i2c", "sifive,i2c0"; + reg = <0x00 0x10030000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x34>; + clocks = <0x01 0x07>; + reg-shift = <0x02>; + reg-io-width = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + u-boot,dm-spl; + + temperature-sensor@4c { + compatible = "ti,tmp451"; + reg = <0x4c>; + interrupt-parent = <0x0b>; + interrupts = <0x06 0x08>; + }; + + pmic@58 { + compatible = "dlg,da9063"; + reg = <0x58>; + interrupt-parent = <0x0b>; + interrupts = <0x01 0x08>; + interrupt-controller; + + regulators { + + bcore1 { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x4c4b40>; + regulator-max-microamp = <0x4c4b40>; + regulator-always-on; + }; + + bcore2 { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x4c4b40>; + regulator-max-microamp = <0x4c4b40>; + regulator-always-on; + }; + + bpro { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x2625a0>; + regulator-max-microamp = <0x2625a0>; + regulator-always-on; + }; + + bperi { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x16e360>; + regulator-max-microamp = <0x16e360>; + regulator-always-on; + }; + + bmem { + regulator-min-microvolt = <0x124f80>; + regulator-max-microvolt = <0x124f80>; + regulator-min-microamp = <0x2dc6c0>; + regulator-max-microamp = <0x2dc6c0>; + regulator-always-on; + }; + + bio { + regulator-min-microvolt = <0x124f80>; + regulator-max-microvolt = <0x124f80>; + regulator-min-microamp = <0x2dc6c0>; + regulator-max-microamp = <0x2dc6c0>; + regulator-always-on; + }; + + ldo1 { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x186a0>; + regulator-max-microamp = <0x186a0>; + regulator-always-on; + }; + + ldo2 { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo3 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo4 { + regulator-min-microvolt = <0x2625a0>; + regulator-max-microvolt = <0x2625a0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo5 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x186a0>; + regulator-max-microamp = <0x186a0>; + regulator-always-on; + }; + + ldo6 { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo7 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo8 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo9 { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + }; + + ldo10 { + regulator-min-microvolt = <0xf4240>; + regulator-max-microvolt = <0xf4240>; + regulator-min-microamp = <0x493e0>; + regulator-max-microamp = <0x493e0>; + }; + + ldo11 { + regulator-min-microvolt = <0x2625a0>; + regulator-max-microvolt = <0x2625a0>; + regulator-min-microamp = <0x493e0>; + regulator-max-microamp = <0x493e0>; + regulator-always-on; + }; + }; + }; + }; + + i2c@10031000 { + compatible = "sifive,fu740-c000-i2c", "sifive,i2c0"; + reg = <0x00 0x10031000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x35>; + clocks = <0x01 0x07>; + reg-shift = <0x02>; + reg-io-width = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + }; + + spi@10040000 { + compatible = "sifive,fu740-c000-spi", "sifive,spi0"; + reg = <0x00 0x10040000 0x00 0x1000 0x00 0x20000000 0x00 0x10000000>; + interrupt-parent = <0x0a>; + interrupts = <0x29>; + clocks = <0x01 0x07>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + + flash@0 { + compatible = "issi,is25wp256", "jedec,spi-nor"; + reg = <0x00>; + spi-max-frequency = <0x2faf080>; + m25p,fast-read; + spi-tx-bus-width = <0x04>; + spi-rx-bus-width = <0x04>; + }; + }; + + spi@10041000 { + compatible = "sifive,fu740-c000-spi", "sifive,spi0"; + reg = <0x00 0x10041000 0x00 0x1000 0x00 0x30000000 0x00 0x10000000>; + interrupt-parent = <0x0a>; + interrupts = <0x2a>; + clocks = <0x01 0x07>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + }; + + spi@10050000 { + compatible = "sifive,fu740-c000-spi", "sifive,spi0"; + reg = <0x00 0x10050000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x2b>; + clocks = <0x01 0x07>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + u-boot,dm-spl; + + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0x00>; + spi-max-frequency = <0x1312d00>; + voltage-ranges = <0xce4 0xce4>; + disable-wp; + u-boot,dm-spl; + }; + }; + + ethernet@10090000 { + compatible = "sifive,fu540-c000-gem"; + interrupt-parent = <0x0a>; + interrupts = <0x37>; + reg = <0x00 0x10090000 0x00 0x2000 0x00 0x100a0000 0x00 0x1000>; + local-mac-address = [00 00 00 00 00 00]; + clock-names = "pclk", "hclk"; + clocks = <0x01 0x02 0x01 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + phy-mode = "gmii"; + phy-handle = <0x0c>; + assigned-clocks = <0x01 0x02>; + assigned-clock-rates = <0x7754188>; + + ethernet-phy@0 { + reg = <0x00>; + phandle = <0x0c>; + }; + }; + + pwm@10020000 { + compatible = "sifive,fu740-c000-pwm", "sifive,pwm0"; + reg = <0x00 0x10020000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x2c 0x2d 0x2e 0x2f>; + clocks = <0x01 0x07>; + #pwm-cells = <0x03>; + status = "okay"; + }; + + pwm@10021000 { + compatible = "sifive,fu740-c000-pwm", "sifive,pwm0"; + reg = <0x00 0x10021000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x30 0x31 0x32 0x33>; + clocks = <0x01 0x07>; + #pwm-cells = <0x03>; + status = "okay"; + }; + + cache-controller@2010000 { + compatible = "sifive,fu740-c000-ccache", "cache"; + cache-block-size = <0x40>; + cache-level = <0x02>; + cache-sets = <0x800>; + cache-size = <0x200000>; + cache-unified; + interrupt-parent = <0x0a>; + interrupts = <0x13 0x15 0x16 0x14>; + reg = <0x00 0x2010000 0x00 0x1000>; + status = "okay"; + phandle = <0x02>; + }; + + gpio@10060000 { + compatible = "sifive,fu740-c000-gpio", "sifive,gpio0"; + interrupt-parent = <0x0a>; + interrupts = <0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26>; + reg = <0x00 0x10060000 0x00 0x1000>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + clocks = <0x01 0x07>; + status = "okay"; + u-boot,dm-spl; + phandle = <0x0b>; + }; + + pcie@e00000000 { + #address-cells = <0x03>; + #interrupt-cells = <0x01>; + #num-lanes = <0x08>; + #size-cells = <0x02>; + compatible = "sifive,fu740-pcie"; + reg = <0x0e 0x00 0x01 0x00 0x0d 0xf0000000 0x00 0x10000000 0x00 0x100d0000 0x00 0x1000>; + reg-names = "dbi", "config", "mgmt"; + device_type = "pci"; + dma-coherent; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0x00 0x60080000 0x00 0x60080000 0x00 0x10000 0x82000000 0x00 0x60090000 0x00 0x60090000 0x00 0xff70000 0x82000000 0x00 0x70000000 0x00 0x70000000 0x00 0x1000000 0xc3000000 0x20 0x00 0x20 0x00 0x20 0x00>; + num-lanes = <0x08>; + interrupts = <0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40>; + interrupt-names = "msi", "inta", "intb", "intc", "intd"; + interrupt-parent = <0x0a>; + interrupt-map-mask = <0x00 0x00 0x00 0x07>; + interrupt-map = <0x00 0x00 0x00 0x01 0x0a 0x39 0x00 0x00 0x00 0x02 0x0a 0x3a 0x00 0x00 0x00 0x03 0x0a 0x3b 0x00 0x00 0x00 0x04 0x0a 0x3c>; + pwren-gpios = <0x0b 0x05 0x00>; + reset-gpios = <0x0b 0x08 0x00>; + clocks = <0x01 0x08>; + clock-names = "pcieaux"; + resets = <0x01 0x04>; + reset-names = "rst_n"; + status = "okay"; + }; + + clint@2000000 { + compatible = "riscv,clint0"; + interrupts-extended = <0x03 0x03 0x03 0x07 0x04 0x03 0x04 0x07 0x05 0x03 0x05 0x07 0x06 0x03 0x06 0x07 0x07 0x03 0x07 0x07>; + reg = <0x00 0x2000000 0x00 0x10000>; + u-boot,dm-spl; + clocks = <0x09>; + }; + + dmc@100b0000 { + compatible = "sifive,fu740-c000-ddr"; + reg = <0x00 0x100b0000 0x00 0x800 0x00 0x100b2000 0x00 0x2000 0x00 0x100b8000 0x00 0x1000>; + clocks = <0x01 0x01>; + clock-frequency = <0x37a1894c>; + u-boot,dm-spl; + sifive,ddr-params = <0xa00 0x00 0x00 0x00 0x00 0x00 0x0a 0x2d362 0x71073 0xa1c0255 0x1c1c0400 0x404c90b 0x2b050405 0xd0c081e 0x8090914 0xfde718 0x180a05 0x8b130d 0x1000118 0xd032001 0x00 0x101 0x00 0xa000000 0x00 0x1450100 0x1c36 0x05 0x170006 0x14e0400 0x3010000 0xa0e00 0x4030200 0x31f 0x70004 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x424 0x201 0x1008 0x00 0x200 0x800 0x481 0x400 0x424 0x201 0x1008 0x00 0x200 0x800 0x481 0x400 0x1010000 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x1000000 0x40000 0x800200 0x200 0x40 0x1000100 0xa000002 0x101ffff 0x1010101 0x1010101 0x10b 0xc03 0x00 0x00 0x00 0x00 0x30300 0x00 0x10101 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x2010102 0x108070d 0x5050300 0x4000503 0x00 0x00 0x00 0x00 0x280d0000 0x1000000 0x00 0x30001 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x1000000 0x01 0x100 0x10303 0x67676701 0x67676767 0x67676767 0x67676767 0x67676767 0x67676767 0x67676767 0x67676767 0x67676767 0x1000067 0x01 0x101 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x7fffff 0x00 0x37fffff 0xffffffff 0xf000f 0xffff03 0xfffff 0x3000f 0xffffffff 0xf000f 0xffff03 0xfffff 0x3000f 0xffffffff 0xf000f 0xffff03 0xfffff 0x3000f 0xffffffff 0xf000f 0xffff03 0xfffff 0x6407000f 0x1640001 0x00 0x00 0x1800 0x386c05 0x2000200 0x2000200 0x386c 0x23438 0x2020d0f 0x140303 0x00 0x00 0x1403 0x00 0x00 0x00 0x00 0xc010000 0x08 0x1375642 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x40263571 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x46052371 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x37651240 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x34216750 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x35176402 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x10526347 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x41753260 0x4c008 0xda 0x00 0x00 0x10000 0x1dddd90 0x1dddd90 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x76543210 0x4c008 0xda 0x00 0x00 0x10000 0x1665555 0x1665555 0x1030001 0x1000000 0xc00000 0x07 0x00 0x00 0x4000408 0x408 0xe4e400 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x200000 0x00 0x00 0x00 0x00 0x00 0x00 0x2800280 0x2800280 0x2800280 0x2800280 0x280 0x00 0x00 0x00 0x00 0x00 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x800080 0x100da 0x1ff0010 0x00 0x00 0x02 0x51313152 0x80013130 0x2000080 0x100001 0xc064208 0xf0c0f 0x1000140 0x0c 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x50000 0x00 0x00 0x00 0x100 0x00 0x00 0x506401 0x1221102 0x122 0x00 0xb1f00 0xb1f0b1f 0xb1f0b1f 0xb1f0b1f 0xb1f0b1f 0xb00 0x42080010 0x1000100 0x1000100 0x1000100 0x1000100 0x00 0x00 0x00 0x00 0x00 0x803 0x223fff00 0x8ff 0x57f 0x57f 0x37fff 0x37fff 0x4410 0x4410 0x4410 0x4410 0x4410 0x111 0x111 0x00 0x00 0x00 0x4000000 0x00 0x00 0x108 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x20100 0x00 0x00>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00 0x80000000 0x04 0x00>; + u-boot,dm-spl; + }; + + hfclk { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <0x18cba80>; + clock-output-names = "hfclk"; + u-boot,dm-spl; + phandle = <0x08>; + }; + + rtcclk { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <0xf4240>; + clock-output-names = "rtcclk"; + u-boot,dm-spl; + phandle = <0x09>; + }; + + gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <0x0b 0x02 0x01>; + }; + + binman { + multiple-images; + + itb { + filename = "u-boot.itb"; + + fit { + description = "Configuration to load OpenSBI before U-Boot"; + #address-cells = <0x01>; + fit,fdt-list = "of-list"; + + images { + + uboot { + description = "U-Boot"; + type = "standalone"; + os = "U-Boot"; + arch = "riscv"; + compression = "none"; + load = <0x80200000>; + + blob-ext { + filename = "u-boot-nodtb.bin"; + }; + }; + + opensbi { + description = "OpenSBI fw_dynamic Firmware"; + type = "firmware"; + os = "opensbi"; + arch = "riscv"; + compression = "none"; + load = <0x80000000>; + entry = <0x80000000>; + + opensbi { + filename = "fw_dynamic.bin"; + }; + }; + + @fdt-SEQ { + description = "NAME"; + type = "flat_dt"; + compression = "none"; + }; + }; + + configurations { + default = "conf-1"; + + @conf-SEQ { + description = "NAME"; + firmware = "opensbi"; + loadables = "uboot"; + fdt = "fdt-SEQ"; + }; + }; + }; + }; + }; +}; diff --git a/src/de.rs b/src/de.rs index b6dd1b4..bd2629f 100644 --- a/src/de.rs +++ b/src/de.rs @@ -77,7 +77,7 @@ where let total_size = u32::from_be(header.total_size); let raw_data_len = (total_size - HEADER_LEN) as usize; - let ans_ptr = core::ptr::from_raw_parts(ptr as *const u8, raw_data_len); + let ans_ptr = core::ptr::from_raw_parts(ptr, raw_data_len); let device_tree: &DeviceTree = &*ans_ptr; let tags = device_tree.tags(); let mut d = Deserializer { diff --git a/src/de_mut/cursor.rs b/src/de_mut/cursor.rs index 1ca239c..df27d65 100644 --- a/src/de_mut/cursor.rs +++ b/src/de_mut/cursor.rs @@ -7,7 +7,6 @@ pub(super) struct AnyCursor(usize, PhantomData); pub(super) type BodyCursor = AnyCursor; pub(super) type TitleCursor = AnyCursor; -pub(super) type GroupCursor = AnyCursor<Group>; pub(super) type PropCursor = AnyCursor<Prop>; pub(super) trait Type {} @@ -17,13 +16,10 @@ pub(super) struct Body {} #[derive(Clone, Copy, Debug)] pub(super) struct Title {} #[derive(Clone, Copy, Debug)] -pub(super) struct Group {} -#[derive(Clone, Copy, Debug)] pub(super) struct Prop {} impl Type for Body {} impl Type for Title {} -impl Type for Group {} impl Type for Prop {} pub enum MoveResult { @@ -107,7 +103,7 @@ impl BodyCursor { self.0 += 1; MoveResult::Others } - _ => todo!(), + _ => todo!("unknown block {}", structure[self.0]), } } @@ -149,10 +145,10 @@ impl TitleCursor { } /// 生成组光标。 - pub fn take_group_on(&self, dtb: RefDtb, name: &str) -> (GroupCursor, usize, BodyCursor) { + pub fn take_group_on(&self, dtb: RefDtb, name: &str) -> (BodyCursor, usize, BodyCursor) { let name_bytes = name.as_bytes(); let name_skip = align(name_bytes.len() + 1, BLOCK_LEN); - let group = AnyCursor::<Group>(self.0, PhantomData); + let group = AnyCursor::<Body>(self.0, PhantomData); let mut body = AnyCursor::<Body>(self.0 + 1 + name_skip, PhantomData); let mut len = 1; @@ -194,57 +190,6 @@ impl TitleCursor { } } -impl GroupCursor { - /// 读取缓存的下一项偏移。 - pub fn offset_on(&self, dtb: RefDtb) -> usize { - (dtb.borrow().structure[self.0].0 >> 8) as _ - } - - /// 利用缓存的名字长度取出名字。 - pub fn name_on<'a>(&self, dtb: RefDtb<'a>) -> (&'a [u8], BodyCursor) { - let structure = &dtb.borrow().structure; - let len_name = (structure[self.0].0 & 0xff) as usize; - let bytes = structure[self.0 + 1].lead_slice(len_name); - ( - bytes, - AnyCursor(self.0 + 1 + align(len_name + 1, BLOCK_LEN), PhantomData), - ) - } - - /// 初始化组反序列化。 - pub fn init_on(&self, dtb: RefDtb, len_item: usize, len_name: usize) { - let mut body = AnyCursor::<Body>(self.0, PhantomData); - for _ in 0..len_item { - let current = body.0; - let len_total = dtb.borrow().structure[current + 1] - .lead_slice(u16::MAX as _) - .iter() - .enumerate() - .skip(len_name + 1) - .find(|(_, b)| **b == b'\0') - .map(|(i, _)| i) - .unwrap(); - body.step_n(align(len_total, BLOCK_LEN)); - body.skip_str_on(dtb); - body.escape_from(dtb); - let off_next = body.0 - current; - dtb.borrow_mut().structure[current].0 = (off_next << 8 | len_total) as _; - } - } - - /// 组结构恢复原状。 - pub fn drop_on(&self, dtb: RefDtb, len_item: usize) { - use StructureBlock as B; - let structure = &mut *dtb.borrow_mut().structure; - let mut i = self.0; - for _ in 0..len_item { - let offset = (structure[i].0 >> 8) as usize; - structure[i] = B::NODE_BEGIN; - i += offset; - } - } -} - impl PropCursor { pub fn name_on<'a>(&self, dtb: RefDtb<'a>) -> (&'a str, BodyCursor) { let dtb = dtb.borrow(); diff --git a/src/de_mut/data.rs b/src/de_mut/data.rs index 970906a..0074c1c 100644 --- a/src/de_mut/data.rs +++ b/src/de_mut/data.rs @@ -1,13 +1,60 @@ -use super::{DtError, PropCursor, RefDtb, RegConfig}; -use serde::de; +use super::{BodyCursor, Cursor}; +use super::{DtError, PropCursor, RefDtb, RegConfig}; -pub(super) struct BorrowedValueDeserializer<'de> { +use core::marker::PhantomData; +use serde::{de, Deserialize}; + +#[derive(Clone, Copy, Debug)] +pub(super) enum ValueCursor { + Prop(BodyCursor, PropCursor), + Body(BodyCursor), +} + +#[derive(Clone, Copy)] +pub(super) struct ValueDeserializer<'de> { pub dtb: RefDtb<'de>, pub reg: RegConfig, - pub cursor: PropCursor, + pub cursor: ValueCursor, } -impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { +impl<'de> Deserialize<'de> for ValueDeserializer<'_> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + struct Visitor<'de, 'b> { + marker: PhantomData<ValueDeserializer<'b>>, + lifetime: PhantomData<&'de ()>, + } + impl<'de, 'b> de::Visitor<'de> for Visitor<'de, 'b> { + type Value = ValueDeserializer<'b>; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(formatter, "struct ValueDeserializer") + } + + fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + Ok(unsafe { + *(*(core::ptr::addr_of!(deserializer) as *const _ as *const &ValueDeserializer)) + }) + } + } + + serde::Deserializer::deserialize_newtype_struct( + deserializer, + super::VALUE_DESERIALIZER_NAME, + Visitor { + marker: PhantomData, + lifetime: PhantomData, + }, + ) + } +} + +impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> { type Error = DtError; fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> @@ -21,14 +68,17 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - let val = self.cursor.map_on(self.dtb, |data| { - if data.is_empty() { - true - } else { - todo!("&[u8] -> bool") - } - }); - visitor.visit_bool(val) + if let ValueCursor::Prop(_, cursor) = self.cursor { + let val = cursor.map_on(self.dtb, |data| { + if data.is_empty() { + true + } else { + todo!("&[u8] -> bool") + } + }); + return visitor.visit_bool(val); + } + unreachable!("Node -> bool"); } fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value, Self::Error> @@ -77,7 +127,10 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - visitor.visit_u32(self.cursor.map_u32_on(self.dtb)?) + if let ValueCursor::Prop(_, cursor) = self.cursor { + return visitor.visit_u32(cursor.map_u32_on(self.dtb)?); + } + unreachable!("node -> u32"); } fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> @@ -108,12 +161,11 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { unreachable!("char") } - fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error> + fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: de::Visitor<'de>, { - let data = self.cursor.data_on(self.dtb); - visitor.visit_borrowed_str(unsafe { core::str::from_utf8_unchecked(data) }) + unreachable!("str"); } fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value, Self::Error> @@ -127,8 +179,11 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - let data = self.cursor.data_on(self.dtb); - visitor.visit_borrowed_bytes(data) + if let ValueCursor::Prop(_, cursor) = self.cursor { + let data = cursor.data_on(self.dtb); + return visitor.visit_borrowed_bytes(data); + } + unreachable!("node -> bytes"); } fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error> @@ -142,11 +197,16 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - let data = self.cursor.data_on(self.dtb); - if data.is_empty() { - visitor.visit_none() - } else { - visitor.visit_some(self) + match self.cursor { + ValueCursor::Prop(_, cursor) => { + let data = cursor.data_on(self.dtb); + if data.is_empty() { + visitor.visit_none() + } else { + visitor.visit_some(self) + } + } + ValueCursor::Body(_) => visitor.visit_some(self), } } @@ -176,41 +236,67 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { where V: de::Visitor<'de>, { - match name { - "StrSeq" => { - let inner = super::str_seq::Inner { - dtb: self.dtb, - cursor: self.cursor, - }; - visitor.visit_borrowed_bytes(unsafe { - core::slice::from_raw_parts( - &inner as *const _ as *const u8, - core::mem::size_of_val(&inner), - ) - }) - } - "Reg" => { - let inner = super::reg::Inner { - dtb: self.dtb, - reg: self.reg, - cursor: self.cursor, - }; - visitor.visit_borrowed_bytes(unsafe { - core::slice::from_raw_parts( - &inner as *const _ as *const u8, - core::mem::size_of_val(&inner), - ) - }) - } - _ => visitor.visit_newtype_struct(self), + if name == super::VALUE_DESERIALIZER_NAME { + return visitor.visit_newtype_struct(self); + } + match self.cursor { + ValueCursor::Prop(_, cursor) => match name { + "StrSeq" => { + let inner = super::str_seq::Inner { + dtb: self.dtb, + cursor, + }; + visitor.visit_borrowed_bytes(unsafe { + core::slice::from_raw_parts( + &inner as *const _ as *const u8, + core::mem::size_of_val(&inner), + ) + }) + } + "Reg" => { + let inner = super::reg::Inner { + dtb: self.dtb, + reg: self.reg, + cursor, + }; + visitor.visit_borrowed_bytes(unsafe { + core::slice::from_raw_parts( + &inner as *const _ as *const u8, + core::mem::size_of_val(&inner), + ) + }) + } + _ => visitor.visit_newtype_struct(self), + }, + ValueCursor::Body(_) => visitor.visit_newtype_struct(self), } } - fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error> + fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: de::Visitor<'de>, { - unreachable!("seq") + use super::{StructAccess, StructAccessType, Temp}; + match self.move_on() { + Cursor::Title(c) => { + let (name, _) = c.split_on(self.dtb); + let cursor = match self.cursor { + ValueCursor::Body(cursor) => cursor, + _ => unreachable!(""), + }; + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + + visitor.visit_seq(StructAccess { + access_type: StructAccessType::Seq(name), + temp: Temp::Node(cursor, cursor), + de: self, + }) + } + _ => unreachable!("seq request on a none seq cursor"), + } } fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> @@ -232,23 +318,39 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { unreachable!("tuple_struct") } - fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value, Self::Error> + fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: de::Visitor<'de>, { - unreachable!("map") + use super::{StructAccess, StructAccessType, Temp}; + if let ValueCursor::Body(cursor) = self.cursor { + return visitor.visit_map(StructAccess { + access_type: StructAccessType::Map(false), + temp: Temp::Node(cursor, cursor), + de: self, + }); + }; + unreachable!("Prop -> map") } fn deserialize_struct<V>( self, _name: &'static str, - _fields: &'static [&'static str], - _visitor: V, + fields: &'static [&'static str], + visitor: V, ) -> Result<V::Value, Self::Error> where V: de::Visitor<'de>, { - unreachable!("struct {_name} {_fields:?}") + use super::{StructAccess, StructAccessType, Temp}; + if let ValueCursor::Body(cursor) = self.cursor { + return visitor.visit_map(StructAccess { + access_type: StructAccessType::Struct(fields), + temp: Temp::Node(cursor, cursor), + de: self, + }); + }; + unreachable!("Prop -> struct {_name} {fields:?}") } fn deserialize_enum<V>( @@ -277,3 +379,34 @@ impl<'de> de::Deserializer<'de> for &mut BorrowedValueDeserializer<'de> { unreachable!("ignored_any") } } + +impl ValueDeserializer<'_> { + #[inline] + pub fn move_on(&mut self) -> super::Cursor { + if let ValueCursor::Body(ref mut cursor) = self.cursor { + return cursor.move_on(self.dtb); + }; + unreachable!("move_on prop cursor"); + } + #[inline] + pub fn step_n(&mut self, n: usize) { + if let ValueCursor::Body(ref mut cursor) = self.cursor { + return cursor.step_n(n); + }; + unreachable!("step_n prop cursor"); + } + #[inline] + pub fn is_complete_on(&self) -> bool { + if let ValueCursor::Body(cursor) = self.cursor { + return cursor.is_complete_on(self.dtb); + }; + unreachable!("is_complete_on prop cursor"); + } + #[inline] + pub fn file_index_on(&self) -> usize { + if let ValueCursor::Body(cursor) = self.cursor { + return cursor.file_index_on(self.dtb); + }; + unreachable!("file_index_on prop cursor"); + } +} diff --git a/src/de_mut/group.rs b/src/de_mut/group.rs deleted file mode 100644 index 4c70202..0000000 --- a/src/de_mut/group.rs +++ /dev/null @@ -1,251 +0,0 @@ -use super::{DtError, GroupCursor, RefDtb, RegConfig}; -use serde::de; - -#[allow(unused)] -#[derive(Clone, Copy)] -pub(super) struct GroupDeserializer<'de> { - pub dtb: RefDtb<'de>, - pub cursor: GroupCursor, - pub reg: RegConfig, - pub len_item: usize, - pub len_name: usize, -} - -impl<'de> de::Deserializer<'de> for &mut GroupDeserializer<'de> { - type Error = DtError; - - fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("any") - } - - fn deserialize_bool<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("bool") - } - - fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i8") - } - - fn deserialize_i16<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i16") - } - - fn deserialize_i32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i32") - } - - fn deserialize_i64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i64") - } - - fn deserialize_u8<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u8") - } - - fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u16") - } - - fn deserialize_u32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u32") - } - - fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u64") - } - - fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("f32") - } - - fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("f64") - } - - fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("char") - } - - fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("str") - } - - fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("string") - } - - fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("bytes") - } - - fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("byte_buf") - } - - fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - visitor.visit_some(self) - } - - fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("unit") - } - - fn deserialize_unit_struct<V>( - self, - _name: &'static str, - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("unit_struct") - } - - fn deserialize_newtype_struct<V>( - self, - name: &'static str, - visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - if name == "NodeSeq" { - visitor.visit_borrowed_bytes(unsafe { - core::slice::from_raw_parts( - self as *const _ as *const u8, - core::mem::size_of::<GroupDeserializer<'_>>(), - ) - }) - } else { - visitor.visit_newtype_struct(self) - } - } - - fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("seq") - } - - fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("tuple") - } - - fn deserialize_tuple_struct<V>( - self, - _name: &'static str, - _len: usize, - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("tuple_struct") - } - - fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("map") - } - - fn deserialize_struct<V>( - self, - _name: &'static str, - _fields: &'static [&'static str], - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("struct") - } - - fn deserialize_enum<V>( - self, - _name: &'static str, - _variants: &'static [&'static str], - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("enum") - } - - fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("identifer") - } - - fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("ignored_any") - } -} diff --git a/src/de_mut/mod.rs b/src/de_mut/mod.rs index e88dd24..2e310a3 100644 --- a/src/de_mut/mod.rs +++ b/src/de_mut/mod.rs @@ -6,25 +6,26 @@ use serde::de; mod cursor; mod data; -mod group; +// mod group; mod node; mod node_seq; mod reg; mod str_seq; -mod r#struct; +// mod r#struct; +mod struct_access; mod structs; +const VALUE_DESERIALIZER_NAME: &str = "$serde_device_tree$de_mut$ValueDeserializer"; + pub use structs::{Dtb, DtbPtr}; pub mod buildin { pub use super::{node::Node, node_seq::NodeSeq, reg::Reg, str_seq::StrSeq}; } -use cursor::{BodyCursor, Cursor, GroupCursor, PropCursor}; -use data::BorrowedValueDeserializer; -use group::GroupDeserializer; -// use node::NodeDeserializer; -use r#struct::StructDeserializer; +use cursor::{BodyCursor, Cursor, PropCursor}; +use data::{ValueCursor, ValueDeserializer}; use reg::RegConfig; +use struct_access::{StructAccess, StructAccessType, Temp}; use structs::{RefDtb, StructureBlock, BLOCK_LEN}; /// 从 [`RefDtb`] 反序列化一个描述设备树的 `T` 类型实例。 @@ -37,135 +38,17 @@ where { // 根节点的名字固定为空字符串, // 从一个跳过根节点名字的光标初始化解析器。 - let mut d = StructDeserializer { + let mut d = ValueDeserializer { dtb, reg: RegConfig::DEFAULT, - cursor: BodyCursor::ROOT, + cursor: ValueCursor::Body(BodyCursor::ROOT), }; T::deserialize(&mut d).and_then(|t| { // 解析必须完成 - if d.cursor.is_complete_on(dtb) { + if d.is_complete_on() { Ok(t) } else { - Err(DtError::deserialize_not_complete( - d.cursor.file_index_on(d.dtb), - )) + Err(DtError::deserialize_not_complete(d.file_index_on())) } }) } - -/// 结构体解析状态。 -struct StructAccess<'de, 'b> { - fields: &'static [&'static str], - temp: Temp, - de: &'b mut StructDeserializer<'de>, -} - -/// 用于跨键-值传递的临时变量。 -/// -/// 解析键(名字)时将确定值类型,保存 `Temp` 类型的状态。 -/// 根据状态分发值解析器。 -enum Temp { - Node(BodyCursor), - Group(GroupCursor, usize, usize), - Prop(PropCursor), -} - -impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { - type Error = DtError; - - fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> - where - K: de::DeserializeSeed<'de>, - { - let name = loop { - match self.de.move_next() { - // 子节点名字 - Cursor::Title(c) => { - let (name, _) = c.split_on(self.de.dtb); - - let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); - // 子节点名字不带 @ - if pre_len == name.as_bytes().len() { - let (node, next) = c.take_node_on(self.de.dtb, name); - self.de.cursor = next; - if self.fields.contains(&name) { - self.temp = Temp::Node(node); - break name; - } - } - // @ 之前的部分是真正的名字,用这个名字搜索连续的一组 - else { - let name_bytes = &name.as_bytes()[..pre_len]; - let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; - let (group, len, next) = c.take_group_on(self.de.dtb, name); - self.de.cursor = next; - if self.fields.contains(&name) { - self.temp = Temp::Group(group, len, name.len()); - break name; - } - } - } - // 属性条目 - Cursor::Prop(c) => { - let (name, next) = c.name_on(self.de.dtb); - self.de.cursor = next; - match name { - "#address-cells" => { - self.de.reg.address_cells = c.map_u32_on(self.de.dtb)?; - } - "#size-cells" => { - self.de.reg.size_cells = c.map_u32_on(self.de.dtb)?; - } - _ => {} - } - if self.fields.contains(&name) { - self.temp = Temp::Prop(c); - break name; - } - } - // 截止符,结构体解析完成 - Cursor::End => { - self.de.cursor.step_n(1); - return Ok(None); - } - } - }; - seed.deserialize(de::value::BorrowedStrDeserializer::new(name)) - .map(Some) - } - - fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> - where - V: de::DeserializeSeed<'de>, - { - match self.temp { - Temp::Node(cursor) => { - // 键是独立节点名字,递归 - seed.deserialize(&mut StructDeserializer { - dtb: self.de.dtb, - cursor, - reg: self.de.reg, - }) - } - Temp::Group(cursor, len_item, len_name) => { - // 键是组名字,构造组反序列化器 - seed.deserialize(&mut GroupDeserializer { - dtb: self.de.dtb, - cursor, - reg: self.de.reg, - len_item, - len_name, - }) - } - Temp::Prop(cursor) => { - // 键是属性名字,构造属性反序列化器 - seed.deserialize(&mut BorrowedValueDeserializer { - dtb: self.de.dtb, - reg: self.de.reg, - cursor, - }) - } - } - } -} diff --git a/src/de_mut/node.rs b/src/de_mut/node.rs index 2e7167b..25b883d 100644 --- a/src/de_mut/node.rs +++ b/src/de_mut/node.rs @@ -1,16 +1,13 @@ -use super::{ - BodyCursor, BorrowedValueDeserializer, Cursor, PropCursor, RefDtb, RegConfig, - StructDeserializer, -}; +use super::{BodyCursor, Cursor, PropCursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; use core::fmt::Debug; use core::marker::PhantomData; +use serde::de::MapAccess; use serde::{de, Deserialize}; #[allow(unused)] #[derive(Clone)] pub struct Node<'de> { dtb: RefDtb<'de>, - cursor: BodyCursor, reg: RegConfig, props_start: Option<BodyCursor>, nodes_start: Option<BodyCursor>, @@ -43,75 +40,29 @@ pub struct PropIter<'de, 'b> { pub struct PropItem<'de> { dtb: RefDtb<'de>, reg: RegConfig, + body: BodyCursor, prop: PropCursor, name: &'de str, } impl<'de> Node<'de> { - unsafe fn covnert_from_struct_deseriallizer_pointer( - ptr: *const &StructDeserializer<'de>, - ) -> Self { - let struct_deseriallizer = &*(ptr); - let dtb = struct_deseriallizer.dtb; - let mut cursor = struct_deseriallizer.cursor; - let mut prop: Option<BodyCursor> = None; - let mut node: Option<BodyCursor> = None; - // TODO: 这里采用朴素的方式遍历块,可能会和 GroupCursor 带来的缓存冲突。 - // 可能需要一个更优雅的缓存方案或者放弃缓存。 - loop { - match cursor.move_on(dtb) { - Cursor::Title(c) => { - let (name, _) = c.split_on(dtb); - let (_, next) = c.take_node_on(dtb, name); - if node.is_none() { - node = Some(cursor) - } - cursor = next; - } - Cursor::Prop(c) => { - let (_, next) = c.name_on(dtb); - if prop.is_none() { - prop = Some(cursor) - } - cursor = next; - } - Cursor::End => { - cursor.move_next(dtb); - break; - } - } - } - Node { - cursor: struct_deseriallizer.cursor, - reg: struct_deseriallizer.reg, - dtb: struct_deseriallizer.dtb, - props_start: prop, - nodes_start: node, - } - } - + // TODO: Maybe use BTreeMap when have alloc /// 获得节点迭代器。 - pub const fn nodes<'b>(&'b self) -> Option<NodeIter<'de, 'b>> { - match self.nodes_start { - None => None, - Some(node_cursor) => Some(NodeIter { - node: self, - cursor: node_cursor, - i: 0, - }), - } + pub fn nodes<'b>(&'b self) -> Option<NodeIter<'de, 'b>> { + self.nodes_start.map(|node_cursor| NodeIter { + node: self, + cursor: node_cursor, + i: 0, + }) } /// 获得属性迭代器。 - pub const fn props<'b>(&'b self) -> Option<PropIter<'de, 'b>> { - match self.props_start { - None => None, - Some(node_cursor) => Some(PropIter { - node: self, - cursor: node_cursor, - i: 0, - }), - } + pub fn props<'b>(&'b self) -> Option<PropIter<'de, 'b>> { + self.props_start.map(|node_cursor| PropIter { + node: self, + cursor: node_cursor, + i: 0, + }) } } @@ -184,6 +135,7 @@ impl<'de> Iterator for PropIter<'de, '_> { let (name, next) = c.name_on(dtb); let res = Some(Self::Item { dtb, + body: self.cursor, reg: self.node.reg, prop: c, name, @@ -211,23 +163,47 @@ impl<'de> Deserialize<'de> for Node<'_> { fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { write!(formatter, "struct Node") } - - fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> where - D: de::Deserializer<'de>, + M: MapAccess<'de>, { - Ok(unsafe { - Node::covnert_from_struct_deseriallizer_pointer(core::ptr::addr_of!( - deserializer - ) - as *const &StructDeserializer) + // While there are entries remaining in the input, add them + // into our map. + let mut dtb: Option<RefDtb<'b>> = None; + let mut reg: Option<RegConfig> = None; + let mut props_start: Option<BodyCursor> = None; + let mut nodes_start: Option<BodyCursor> = None; + while let Some((key, value)) = access.next_entry::<&str, ValueDeserializer<'b>>()? { + dtb = Some(value.dtb); + reg = Some(value.reg); + if key == "/" { + continue; + } + match value.cursor { + ValueCursor::Prop(cursor, _) => { + if props_start.is_none() { + props_start = Some(cursor); + } + } + ValueCursor::Body(cursor) => { + if nodes_start.is_none() { + nodes_start = Some(cursor); + } + } + } + } + + Ok(Node { + dtb: dtb.unwrap(), + reg: reg.unwrap(), + nodes_start, + props_start, }) } } - serde::Deserializer::deserialize_newtype_struct( + serde::Deserializer::deserialize_map( deserializer, - "Node", Visitor { marker: PhantomData, lifetime: PhantomData, @@ -239,10 +215,10 @@ impl<'de> Deserialize<'de> for Node<'_> { impl<'de> NodeItem<'de> { /// 反序列化一个节点的内容。 pub fn deserialize<T: Deserialize<'de>>(&self) -> T { - T::deserialize(&mut StructDeserializer { + T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - cursor: self.node, + cursor: ValueCursor::Body(self.node), }) .unwrap() } @@ -274,10 +250,11 @@ impl<'de> PropItem<'de> { self.name } pub fn deserialize<T: Deserialize<'de>>(&self) -> T { - T::deserialize(&mut BorrowedValueDeserializer { + use super::ValueCursor; + T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - cursor: self.prop, + cursor: ValueCursor::Prop(self.body, self.prop), }) .unwrap() } diff --git a/src/de_mut/node_seq.rs b/src/de_mut/node_seq.rs index d8f61e3..f3d1089 100644 --- a/src/de_mut/node_seq.rs +++ b/src/de_mut/node_seq.rs @@ -1,6 +1,6 @@ -use super::{BodyCursor, GroupCursor, RefDtb, RegConfig, StructDeserializer}; -use crate::de_mut::GroupDeserializer; +use super::{BodyCursor, Cursor, RefDtb, RegConfig, ValueCursor, ValueDeserializer}; use core::{fmt::Debug, marker::PhantomData}; +use serde::de::SeqAccess; use serde::{de, Deserialize}; /// 一组名字以 `@...` 区分,同类、同级且连续的节点的映射。 @@ -9,13 +9,15 @@ use serde::{de, Deserialize}; /// 因此这些节点将延迟解析。 /// 迭代 `NodeSeq` 可获得一系列 [`NodeSeqItem`],再调用 `deserialize` 方法分别解析每个节点。 pub struct NodeSeq<'de> { - inner: GroupDeserializer<'de>, + name: &'de str, + count: usize, + starter: ValueDeserializer<'de>, } /// 连续节点迭代器。 pub struct NodeSeqIter<'de, 'b> { seq: &'b NodeSeq<'de>, - cursor: GroupCursor, + de: ValueDeserializer<'de>, i: usize, } @@ -40,28 +42,43 @@ impl<'de> Deserialize<'de> for NodeSeq<'_> { type Value = NodeSeq<'b>; fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(formatter, "struct StrSeq") + write!(formatter, "struct ValueDeserializer") } - fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> + fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> where - E: de::Error, + A: SeqAccess<'de>, { - // 结构体转为内存切片,然后拷贝过来 - if v.len() == core::mem::size_of::<Self::Value>() { - Ok(Self::Value::from_raw_inner_parts(v.as_ptr())) - } else { - Err(E::invalid_length( - v.len(), - &"`NodeSeq` is copied with wrong size.", - )) + let mut starter: Option<ValueDeserializer> = None; + let mut count = 0; + while let Some(node) = seq.next_element()? { + if starter.is_none() { + starter = Some(node); + } + count += 1 + } + let mut starter = starter.unwrap(); + + match starter.move_on() { + Cursor::Title(c) => { + let (name, _) = c.split_on(starter.dtb); + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + Ok(NodeSeq { + name, + count, + starter, + }) + } + _ => unreachable!("NodeSeq should be inited by a node"), } } } - serde::Deserializer::deserialize_newtype_struct( + serde::Deserializer::deserialize_seq( deserializer, - "NodeSeq", Visitor { marker: PhantomData, lifetime: PhantomData, @@ -71,22 +88,9 @@ impl<'de> Deserialize<'de> for NodeSeq<'_> { } impl<'de> NodeSeq<'de> { - fn from_raw_inner_parts(ptr: *const u8) -> Self { - // 直接从指针拷贝 - let original_inner = unsafe { &*(ptr as *const GroupDeserializer<'_>) }; - let res = Self { - inner: *original_inner, - }; - // 初始化 - res.inner - .cursor - .init_on(res.inner.dtb, res.inner.len_item, res.inner.len_name); - res - } - /// 连续节点总数。 pub const fn len(&self) -> usize { - self.inner.len_item + self.count } /// 如果连续节点数量为零,返回 true。但连续节点数量不可能为零。 @@ -98,7 +102,7 @@ impl<'de> NodeSeq<'de> { pub const fn iter<'b>(&'b self) -> NodeSeqIter<'de, 'b> { NodeSeqIter { seq: self, - cursor: self.inner.cursor, + de: self.starter, i: 0, } } @@ -119,32 +123,42 @@ impl Debug for NodeSeq<'_> { } } -impl Drop for NodeSeq<'_> { - fn drop(&mut self) { - self.inner - .cursor - .drop_on(self.inner.dtb, self.inner.len_item); - } -} - impl<'de> Iterator for NodeSeqIter<'de, '_> { type Item = NodeSeqItem<'de>; fn next(&mut self) -> Option<Self::Item> { - if self.i >= self.seq.inner.len_item { + if self.i >= self.seq.len() { None } else { self.i += 1; - let dtb = self.seq.inner.dtb; - let (name, body) = self.cursor.name_on(dtb); - let off_next = self.cursor.offset_on(dtb); - self.cursor.step_n(off_next); - Some(Self::Item { - dtb, - reg: self.seq.inner.reg, - body, - at: unsafe { core::str::from_utf8_unchecked(&name[self.seq.inner.len_name + 1..]) }, - }) + match self.de.move_on() { + // 子节点名字 + Cursor::Title(c) => { + let (full_name, _) = c.split_on(self.de.dtb); + let (node, next) = c.take_node_on(self.de.dtb, full_name); + + let pre_len = full_name + .as_bytes() + .iter() + .take_while(|b| **b != b'@') + .count(); + let name_bytes = &full_name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + if self.seq.name != name { + return None; + } + + self.de.cursor = ValueCursor::Body(next); + + Some(Self::Item { + dtb: self.de.dtb, + reg: self.de.reg, + body: node, + at: &full_name[pre_len + 1..], + }) + } + _ => None, + } } } } @@ -159,10 +173,10 @@ impl NodeSeqItem<'_> { impl<'de> NodeSeqItem<'de> { /// 反序列化一个节点的内容。 pub fn deserialize<T: Deserialize<'de>>(&self) -> T { - T::deserialize(&mut StructDeserializer { + T::deserialize(&mut ValueDeserializer { dtb: self.dtb, reg: self.reg, - cursor: self.body, + cursor: ValueCursor::Body(self.body), }) .unwrap() } diff --git a/src/de_mut/struct.rs b/src/de_mut/struct.rs deleted file mode 100644 index 7c81542..0000000 --- a/src/de_mut/struct.rs +++ /dev/null @@ -1,250 +0,0 @@ -use super::{BodyCursor, Cursor, DtError, RefDtb, RegConfig, StructAccess, Temp}; -use serde::de; - -#[derive(Clone)] -pub(super) struct StructDeserializer<'de> { - pub dtb: RefDtb<'de>, - pub reg: RegConfig, - pub cursor: BodyCursor, -} - -impl<'de> de::Deserializer<'de> for &mut StructDeserializer<'de> { - type Error = DtError; - - fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("any") - } - - fn deserialize_bool<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("bool") - } - - fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i8") - } - - fn deserialize_i16<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i16") - } - - fn deserialize_i32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i32") - } - - fn deserialize_i64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("i64") - } - - fn deserialize_u8<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u8") - } - - fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u16") - } - - fn deserialize_u32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u32") - } - - fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("u64") - } - - fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("f32") - } - - fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("f64") - } - - fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("char") - } - - fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("str") - } - - fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("string") - } - - fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("bytes") - } - - fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("byte_buf") - } - - fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - visitor.visit_some(self) - } - - fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("unit") - } - - fn deserialize_unit_struct<V>( - self, - _name: &'static str, - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("unit_struct") - } - - fn deserialize_newtype_struct<V>( - self, - _name: &'static str, - visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - visitor.visit_newtype_struct(self) - } - - fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("seq") - } - - fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("tuple") - } - - fn deserialize_tuple_struct<V>( - self, - _name: &'static str, - _len: usize, - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("tuple_struct") - } - - fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("map") - } - - fn deserialize_struct<V>( - self, - _name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - visitor.visit_map(StructAccess { - fields, - temp: Temp::Node(self.cursor), - de: self, - }) - } - - fn deserialize_enum<V>( - self, - _name: &'static str, - _variants: &'static [&'static str], - _visitor: V, - ) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("enum") - } - - fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("identifer") - } - - fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> - where - V: de::Visitor<'de>, - { - todo!("ignored_any") - } -} - -impl StructDeserializer<'_> { - #[inline] - pub fn move_next(&mut self) -> Cursor { - self.cursor.move_on(self.dtb) - } -} diff --git a/src/de_mut/struct_access.rs b/src/de_mut/struct_access.rs new file mode 100644 index 0000000..13e86ac --- /dev/null +++ b/src/de_mut/struct_access.rs @@ -0,0 +1,199 @@ +use super::{BodyCursor, Cursor, PropCursor, ValueCursor, ValueDeserializer}; +use crate::error::Error as DtError; +use serde::de; + +// For map type, we should send root item to trans dtb and reg +pub enum StructAccessType<'de> { + Map(bool), + Seq(&'de str), + Struct(&'static [&'static str]), +} + +/// 结构体解析状态。 +pub struct StructAccess<'de, 'b> { + pub access_type: StructAccessType<'de>, + pub temp: Temp, + pub de: &'b mut ValueDeserializer<'de>, +} + +/// 用于跨键-值传递的临时变量。 +/// +/// 解析键(名字)时将确定值类型,保存 `Temp` 类型的状态。 +/// 根据状态分发值解析器。 +pub enum Temp { + Node(BodyCursor, BodyCursor), + Group(BodyCursor), + Prop(BodyCursor, PropCursor), +} + +impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> { + type Error = DtError; + + fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> + where + K: de::DeserializeSeed<'de>, + { + if let StructAccessType::Map(flag) = self.access_type { + if !flag { + return seed + .deserialize(de::value::BorrowedStrDeserializer::new("/")) + .map(Some); + } + } + let check_contains = |name: &str| -> bool { + match self.access_type { + StructAccessType::Struct(fields) => fields.contains(&name), + _ => true, + } + }; + let name = loop { + let origin_cursor = match self.de.cursor { + ValueCursor::Body(cursor) => cursor, + _ => unreachable!("map access's cursor should always be body cursor"), + }; + match self.de.move_on() { + // 子节点名字 + Cursor::Title(c) => { + let (name, _) = c.split_on(self.de.dtb); + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + // 子节点名字不带 @ 或正在解析 Node 类型 + if pre_len == name.as_bytes().len() || check_contains(name) { + let (node, next) = c.take_node_on(self.de.dtb, name); + self.de.cursor = ValueCursor::Body(next); + if check_contains(name) { + self.temp = Temp::Node(origin_cursor, node); + break name; + } + } + // @ 之前的部分是真正的名字,用这个名字搜索连续的一组 + else { + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + let (group, _, next) = c.take_group_on(self.de.dtb, name); + self.de.cursor = ValueCursor::Body(next); + if check_contains(name) { + self.temp = Temp::Group(group); + break name; + } + } + } + // 属性条目 + Cursor::Prop(c) => { + let (name, next) = c.name_on(self.de.dtb); + self.de.cursor = ValueCursor::Body(next); + match name { + "#address-cells" => { + self.de.reg.address_cells = c.map_u32_on(self.de.dtb)?; + } + "#size-cells" => { + self.de.reg.size_cells = c.map_u32_on(self.de.dtb)?; + } + _ => {} + } + if check_contains(name) { + self.temp = Temp::Prop(origin_cursor, c); + break name; + } + } + // 截止符,结构体解析完成 + Cursor::End => { + self.de.step_n(1); + return Ok(None); + } + } + }; + seed.deserialize(de::value::BorrowedStrDeserializer::new(name)) + .map(Some) + } + + fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> + where + V: de::DeserializeSeed<'de>, + { + if let StructAccessType::Map(ref mut flag) = self.access_type { + if !*flag { + *flag = true; + return seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: self.de.cursor, + }); + } + } + match self.temp { + Temp::Node(cursor, node_cursor) => { + // 键是独立节点名字,递归 + match self.access_type { + StructAccessType::Map(_) => seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(cursor), + }), + StructAccessType::Struct(_) => seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(node_cursor), + }), + _ => unreachable!(), + } + } + Temp::Group(cursor) => { + // 键是组名字,构造组反序列化器 + seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(cursor), + }) + } + Temp::Prop(origin_cursor, cursor) => { + // 键是属性名字,构造属性反序列化器 + seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Prop(origin_cursor, cursor), + }) + } + } + } +} + +impl<'de> de::SeqAccess<'de> for StructAccess<'de, '_> { + type Error = DtError; + + fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> + where + K: de::DeserializeSeed<'de>, + { + if let StructAccessType::Seq(pre_name) = self.access_type { + match self.de.move_on() { + // 子节点名字 + Cursor::Title(c) => { + let (name, _) = c.split_on(self.de.dtb); + let (_, next) = c.take_node_on(self.de.dtb, name); + let prev_cursor = match self.de.cursor { + ValueCursor::Body(cursor) => cursor, + _ => unreachable!(), + }; + + let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count(); + let name_bytes = &name.as_bytes()[..pre_len]; + let name = unsafe { core::str::from_utf8_unchecked(name_bytes) }; + if pre_name != name { + return Ok(None); + } + self.de.cursor = ValueCursor::Body(next); + seed.deserialize(&mut ValueDeserializer { + dtb: self.de.dtb, + reg: self.de.reg, + cursor: ValueCursor::Body(prev_cursor), + }) + .map(Some) + } + _ => Ok(None), + } + } else { + unreachable!("SeqAccess should only be accessed by seq"); + } + } +} diff --git a/src/de_mut/structs.rs b/src/de_mut/structs.rs index acd9c17..88b5481 100644 --- a/src/de_mut/structs.rs +++ b/src/de_mut/structs.rs @@ -94,6 +94,7 @@ impl StructureBlock { /// 构造字节切片。 /// /// TODO + #[allow(unused)] pub fn lead_slice<'a>(&self, len: usize) -> &'a [u8] { unsafe { core::slice::from_raw_parts(self as *const _ as *const u8, len) } } diff --git a/src/lib.rs b/src/lib.rs index f7ab02e..c5333c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ extern crate alloc; pub mod de; pub mod error; +pub mod utils; mod common; mod de_mut; diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 0000000..f255250 --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1,108 @@ +use crate::buildin::Node; + +impl Node<'_> { + /// Try to get a node by path + pub fn find(&self, path: &str) -> Option<Node> { + // Direct return root node + let mut current_node = Some(self.clone()); + if path == "/" { + return current_node; + } + let (root, path) = path.split_at(1); + if root != "/" { + return None; + } + // Split path with / and find each level + for current_name in path.split('/') { + let node = match current_node.clone() { + Some(node) => node, + None => break, + }; + let mut nodes = match node.nodes() { + Some(nodes) => nodes, + None => { + current_node = None; + break; + } + }; + let next_node_iter = nodes.find(|x| x.get_full_name() == current_name); + match next_node_iter { + None => current_node = None, + Some(iter) => { + let next_node = iter.deserialize::<Node>(); + current_node = Some(next_node); + } + } + } + current_node + } + + /// use depth-first search to traversal the tree, and exec func for each node + pub fn search<F>(&self, func: &mut F) + where + F: FnMut(&Node), + { + func(self); + if let Some(nodes) = self.nodes() { + for node in nodes { + let node = node.deserialize::<Node>(); + node.search(func); + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::{ + buildin::{Node, StrSeq}, + from_raw_mut, Dtb, DtbPtr, + }; + static RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/hifive-unmatched-a00.dtb"); + const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); + #[repr(align(8))] + struct AlignedBuffer { + pub data: [u8; RAW_DEVICE_TREE.len()], + } + #[test] + fn test_search() { + let mut aligned_data: Box<AlignedBuffer> = Box::new(AlignedBuffer { + data: [0; BUFFER_SIZE], + }); + aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE); + let mut slice = aligned_data.data.to_vec(); + let ptr = DtbPtr::from_raw(slice.as_mut_ptr()).unwrap(); + let dtb = Dtb::from(ptr).share(); + + let node: Node = from_raw_mut(&dtb).unwrap(); + let mut count = 0; + let mut closure = |_node: &Node| count += 1; + node.search(&mut closure); + assert_eq!(count, 70); + } + #[test] + fn test_find() { + let mut aligned_data: Box<AlignedBuffer> = Box::new(AlignedBuffer { + data: [0; BUFFER_SIZE], + }); + aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE); + let mut slice = aligned_data.data.to_vec(); + let ptr = DtbPtr::from_raw(slice.as_mut_ptr()).unwrap(); + let dtb = Dtb::from(ptr).share(); + + let node: Node = from_raw_mut(&dtb).unwrap(); + let node = node.find("/chosen").unwrap(); + let result = node + .props() + .unwrap() + .find(|prop| prop.get_name() == "stdout-path"); + match result { + Some(iter) => { + if iter.deserialize::<StrSeq>().iter().next().unwrap() != "serial0" { + panic!("wrong /chosen/stdout-path value"); + } + } + None => panic!("failed to find /chosen/stdout-path"), + } + } +} diff --git a/tests/hifive-unmatched-a00.rs b/tests/hifive-unmatched-a00.rs index eea8ef9..e01238a 100644 --- a/tests/hifive-unmatched-a00.rs +++ b/tests/hifive-unmatched-a00.rs @@ -55,5 +55,5 @@ fn hifive_unmatched() { } } assert_eq!(t.cpus.timebase_frequency, 1000000); - assert_eq!(t.cpus.u_boot_dm_spl, true); + assert!(t.cpus.u_boot_dm_spl); } diff --git a/tests/qemu-virt.rs b/tests/qemu-virt.rs new file mode 100644 index 0000000..0fdc5ad --- /dev/null +++ b/tests/qemu-virt.rs @@ -0,0 +1,52 @@ +// 在实际使用中,将这里的 `serde_derive::Deserialize` 改为 `serde::Deserialize`。 +use serde_derive::Deserialize; + +use serde_device_tree::{ + buildin::{NodeSeq, Reg}, + error::Error, + from_raw_mut, Dtb, DtbPtr, +}; + +const RAW_DEVICE_TREE: &[u8] = include_bytes!("../examples/qemu-virt.dtb"); +const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len(); + +#[repr(align(8))] +struct AlignedBuffer { + pub data: [u8; RAW_DEVICE_TREE.len()], +} + +#[derive(Deserialize)] +struct Tree<'a> { + soc: Soc<'a>, +} + +#[allow(dead_code)] +#[derive(Deserialize)] +struct Soc<'a> { + virtio_mmio: NodeSeq<'a>, +} + +#[derive(Deserialize)] +#[allow(unused)] +struct VirtIoMmio<'a> { + reg: Reg<'a>, +} + +#[test] +fn qemu_virt() -> Result<(), Error> { + // 整个设备树二进制文件需要装载到一块可写的内存区域 + let mut aligned_data: Box<AlignedBuffer> = Box::new(AlignedBuffer { + data: [0; BUFFER_SIZE], + }); + aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE); + let mut slice = aligned_data.data.to_vec(); + let ptr = DtbPtr::from_raw(slice.as_mut_ptr())?; + let dtb = Dtb::from(ptr).share(); + + let t: Tree = from_raw_mut(&dtb).unwrap(); + + assert_eq!(t.soc.virtio_mmio.len(), 8); + assert_eq!(slice, RAW_DEVICE_TREE); + + Ok(()) +}