20171024_jeffrey - silenceuncrio/diary GitHub Wiki

0905

早上幫女兒報完戶口了

0935

來整理目前 emmc 可開機的 uboot env

printenv 的結果如下

baudrate=115200
boot_fdt=try
bootcmd=mmc dev ${mmcdev};mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else run netboot; fi
bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr};
bootdelay=3
bootscript=echo Running bootscript from mmc ...; source
console=ttymxc0
ethact=FEC1
ethprime=FEC
fdt_addr=0x83000000
fdt_file=imx6ul-14x14-evk.dtb
fdt_high=0xffffffff
image=zImage
initrd_addr=0x83800000
initrd_high=0xffffffff
ip_dyn=yes
loadaddr=0x80800000
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc g_mass_storage.stall=0 g_mass_storage.removable=1 g_mass_storage.file=/fat g_mass_storage.ro=1 g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF g_mass_storage.iSerialNumber="" clk_ignore_unused
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
mmcautodetect=yes
mmcboot=echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
mmcdev=1
mmcpart=1
mmcroot=/dev/mmcblk1p2 rootwait rw
netargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
netboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${image}; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if ${get_cmd} ${fdt_addr} ${fdt_file}; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
panel=TFT43AB
script=boot.scr

Environment size: 2059/8188 bytes
=>

來整理一下

bootcmd 開始

bootcmd=mmc dev ${mmcdev};mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else run netboot; fi

整理成方便看的樣子

bootcmd=

mmc dev ${mmcdev}; 
mmc dev ${mmcdev}; 

if mmc rescan; 
  then if run loadbootscript; 
    then run bootscript; 
    else if run loadimage; 
      then run mmcboot; 
      else run netboot; 
    fi; 
  fi; 
  else run netboot; 
fi

分析 mmc dev ${mmcdev};

利用 printenv mmcdev 得到 ${mmcdev} 的值

=> printenv mmcdev
mmcdev=1

所以 mmc dev ${mmcdev}; 等同於 mmc dev 1;

mmc dev 指令說明如下

mmc dev [dev] [part] - show or set current mmc device [partition]

mmc dev 1 執行結果如下

=> mmc dev 1
switch to partitions #0, OK
mmc1(part 0) is current device
=>

但不明白為何 bootcmd 一開始就要執行兩次的 mmc dev 1

mmc rescan 沒有什麼說明

不過透過以下的指令可確認 mmc rescan 的執行結果是 true

=> setenv xxx 'if mmc rescan; then echo mmc rescan ok; else echo mmc recan fail; fi'
=> printenv xxx
xxx=if mmc rescan; then echo mmc rescan ok; else echo mmc recan fail; fi
=> run xxx
mmc rescan ok
=>

所以可以再化簡下述的 block

if mmc rescan; 
  then if run loadbootscript; 
    then run bootscript; 
    else if run loadimage; 
      then run mmcboot; 
      else run netboot; 
    fi; 
  fi; 
  else run netboot; 
fi

變成

if run loadbootscript; 
  then run bootscript; 
  else if run loadimage; 
    then run mmcboot; 
    else run netboot; 
  fi; 
fi; 

檢查 loadbootscript

=> printenv loadbootscript
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};

直接來判定一下 run loadbootscript 會怎樣好了

=> setenv yyy 'if run loadbootscript; then echo loadbootscript ok; else echo loadbootscript fail; fi;'
=> run yyy
reading boot.scr
** Unable to read file boot.scr **
loadbootscript fail

繼續化簡

if run loadbootscript; 
  then run bootscript; 
  else if run loadimage; 
    then run mmcboot; 
    else run netboot; 
  fi; 
fi; 

變成

if run loadimage; 
  then run mmcboot; 
  else run netboot; 
fi; 

檢查 loadimage

=> printenv loadimage
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
=>

把需要的變數解開

  • ${mmcdev} = 1
  • ${mmcpart} = 1
  • ${loadaddr} = 0x80800000
  • ${image} = zImage

得到 loadimage = fatload mmc 1:1 0x80800000 zImage

fatload 說明如下

fatload - load binary file from a dos filesystem

Usage:
fatload <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]
    - Load binary file 'filename' from 'dev' on 'interface'
      to address 'addr' from dos filesystem.
      'pos' gives the file position to start loading from.
      If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.
      'bytes' gives the size to load. If 'bytes' is 0 or omitted,
      the load stops on end of file.
      If either 'pos' or 'bytes' are not aligned to
      ARCH_DMA_MINALIGN then a misaligned buffer warning will
      be printed and performance will suffer for the load.

參考 fatload 的說明來幫 fatload mmc 1:1 0x80800000 zImage 解釋一下

Load binary file zImage from 1:1 on mmc to address 0x80800000 from dos filesystem.

判定一下 run loadimage 會怎樣好了

=> setenv zzz 'if run loadimage; then echo loadimage ok; else echo loadimage fail; fi;'
=> run zzz
reading zImage
4993904 bytes read in 126 ms (37.8 MiB/s)
loadimage ok

化簡

if run loadimage; 
  then run mmcboot; 
  else run netboot; 
fi; 

變成

run loadimage; 
run mmcboot; 

檢查 mmcboot

=> printenv mmcboot
mmcboot=echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;

一樣整理成容易解析的格式

mmcboot=

echo Booting from mmc ...; 
run mmcargs; 

if test ${boot_fdt} = yes || test ${boot_fdt} = try; 
  then if run loadfdt; 
    then bootz ${loadaddr} - ${fdt_addr}; 
    else if test ${boot_fdt} = try; 
      then bootz; else echo WARN: Cannot load the DT; 
    fi; 
  fi; 
  else bootz; 
fi;

檢查 mmcargs

=> printenv mmcargs
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}

解開變數

  • ${console} = ttymxc0
  • ${baudrate} = 115200
  • ${mmcroot} = /dev/mmcblk1p2 rootwait rw

得到 mmcargs = setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw

解析

if test ${boot_fdt} = yes || test ${boot_fdt} = try; 
  then if run loadfdt; 
    then bootz ${loadaddr} - ${fdt_addr}; 
    else if test ${boot_fdt} = try; 
      then bootz; else echo WARN: Cannot load the DT; 
    fi; 
  fi; 
  else bootz; 
fi;

檢查 boot_fdt

=> printenv boot_fdt
boot_fdt=try

可以化簡

if test ${boot_fdt} = yes || test ${boot_fdt} = try; 
  then if run loadfdt; 
    then bootz ${loadaddr} - ${fdt_addr}; 
    else if test ${boot_fdt} = try; 
      then bootz; else echo WARN: Cannot load the DT; 
    fi; 
  fi; 
  else bootz; 
fi;

變成

if run loadfdt; 
  then bootz ${loadaddr} - ${fdt_addr}; 
  else if test ${boot_fdt} = try; 
    then bootz; else echo WARN: Cannot load the DT; 
  fi; 
fi; 

檢查 loadfdt

=> printenv loadfdt
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}

解開變數

  • ${mmcdev} = 1
  • ${mmcpart} = 1
  • ${fdt_addr} = 0x83000000
  • ${fdt_file} = 14x14-evk.dtb

得到 loadfdt = fatload mmc 1:1 0x83000000 14x14-evk.dtb

參考 fatload 的說明來解釋一下

Load binary file 14x14-evk.dtb from 1:1 on mmc to address 0x83000000 from dos filesystem.

可以再化簡

if run loadfdt; 
  then bootz ${loadaddr} - ${fdt_addr}; 
  else if test ${boot_fdt} = try; 
    then bootz; else echo WARN: Cannot load the DT; 
  fi; 
fi; 

變成

run loadfdt; 
bootz ${loadaddr} - ${fdt_addr}; 

也就是

run loadfdt; 
bootz 0x80800000 - 0x83000000; 

1300

俐落地從 bootcmd 再開始整理最簡單的樣子

bootcmd=
mmc dev ${mmcdev}; 
mmc dev ${mmcdev}; 
mmc rescan; 
run loadimage; 
run mmcboot; 

整理 loadimage

loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}

整理 mmcboot

mmcboot=

echo Booting from mmc ...; 
run mmcargs; 
run loadfdt; 
bootz ${loadaddr} - ${fdt_addr}; 

整理 mmcargs

mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}

整理 loadfdt

loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}

mmcbootrun 的敘述展開得到

整理 mmcboot

mmcboot=

echo Booting from mmc ...; 
setenv bootargs console=${console},${baudrate} root=${mmcroot}
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
bootz ${loadaddr} - ${fdt_addr}; 

再把 bootcmdrun 的敘述展開

bootcmd=
mmc dev ${mmcdev}; 
mmc dev ${mmcdev}; 
mmc rescan; 
fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
echo Booting from mmc ...; 
setenv bootargs console=${console},${baudrate} root=${mmcroot}
fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
bootz ${loadaddr} - ${fdt_addr}; 

重新整理一下 bootcmd

bootcmd=
mmc dev ${mmcdev}; 
mmc dev ${mmcdev}; 
mmc rescan; 
setenv bootargs console=${console},${baudrate} root=${mmcroot}
fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
bootz ${loadaddr} - ${fdt_addr}; 

也就是 emmc 裡的 uboot 做了下述這些事

  • mmc dev ${mmcdev};
  • mmc dev ${mmcdev};
  • mmc rescan;
  • setenv bootargs console=${console},${baudrate} root=${mmcroot}
  • fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
  • fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
  • bootz ${loadaddr} - ${fdt_addr};

慶幸的是 uboot 並不用參與 emmc 怎麼切割 partition

dual image 的實作在 uboot 上應該只要控制 mmcrootmmcpart 就可以了

mfgtool 要負責把 emmc 切割成我們要的 partition layout

再來應該都是我們自己軟體應用層面的事了

1345

剛剛跟 ariel 聊一下關於 4GB emmc 的初步 partition 規劃

有以下的幾個結論

  • 我們的應用就佔 1GB 就好
    • uboot
    • kernel
    • rootfs
    • dual image layout
  • 剩下的就切成一整個, format 成 ext3 格式方便後續利用
    • user data

就朝這個結論來規劃一下實作面的 layout 吧

1435

一樣先拿 SD 卡搭 隨身碟來做實驗

利用 dd if=/dev/zero of=/dev/sdb bs=1024 count=1 清掉分割表

➜  OS Firmware git:(develop) ✗ cat /proc/partitions
major minor  #blocks  name

  11        0    1048575 sr0
   8        0  125829120 sda
   8        1  123730944 sda1
   8        2          1 sda2
   8        5    2095104 sda5
   8       16    7761920 sdb
   8       17     512000 sdb1
   8       18     368640 sdb2
   8       19    6713344 sdb3
➜  OS Firmware git:(develop) ✗ sudo dd if=/dev/zero of=/dev/sdb bs=1024 count=1
[sudo] password for jeffrey:
1+0 records in
1+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.157767 s, 6.5 kB/s
➜  OS Firmware git:(develop) ✗ cat /proc/partitions
major minor  #blocks  name

  11        0    1048575 sr0
   8        0  125829120 sda
   8        1  123730944 sda1
   8        2          1 sda2
   8        5    2095104 sda5
   8       16    7761920 sdb

1520

利用 sfdisk 分割 partition 要突破 4 個 partition 的限制需要一點小技巧

參考 Issues while eMMC partitioned using sfdisk

1650

搭配以下的 mksdcard.sh

#!/bin/sh

# partition size in MB
BOOT_ROM_SIZE=10

# wait for the SD/MMC device node ready
while [ ! -e $1 ]
do
sleep 1
echo “wait for $1 appear”
done

# call sfdisk to create partition table
# destroy the partition table
node=$1
dd if=/dev/zero of=${node} bs=1024 count=1

sfdisk --force ${node} << EOF
${BOOT_ROM_SIZE}M,40M,C
50M,40M,C
90M,,E
100M,400M,L
500M,400M,L
900M,40M,L
940M,40M,L
1G,,L
EOF

我可以成功的把 emmc 分割成以下樣子

Disk /dev/mmcblk1: 3.6 GiB, 3850371072 bytes, 7520256 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x464ae3d5

Device         Boot   Start     End Sectors  Size Id Type
/dev/mmcblk1p1        20480  102399   81920   40M  c W95 FAT32 (LBA)
/dev/mmcblk1p2       102400  184319   81920   40M  c W95 FAT32 (LBA)
/dev/mmcblk1p3       184320 7520255 7335936  3.5G  5 Extended
/dev/mmcblk1p5       204800 1023999  819200  400M 83 Linux
/dev/mmcblk1p6      1024000 1843199  819200  400M 83 Linux
/dev/mmcblk1p7      1843201 1925119   81919   40M 83 Linux
/dev/mmcblk1p8      1925121 2007039   81919   40M 83 Linux
/dev/mmcblk1p9      2097152 7520255 5423104  2.6G 83 Linux
⚠️ **GitHub.com Fallback** ⚠️