잘 쓰던 포고플러그가 어느 날 먹통이 되더니 부팅이 되지 않는다. OS가 깔려있는 SD카드는 멀쩡한데, 설마 MTD가 나갔나? 안되는 납땜 실력으로 간신히 시리얼 케이블을 붙이고 들여다보니 usb, sd카드, sata 부팅을 시도하고 있고, 모두 실패하니까 비상용으로 설정해두었던 순정 OS로 부팅이 되어 있는 상태였다. 그러나 rootfs (/) 가 마운트가 안되었고, 결과적으로 아무것도 할 수가 없는 상태였다.

여하튼 이참에 시스템도 갈아엎고, 삽질 한번 다시 해보기로..

복구 과정을 요약하면 아래와 같다.
- Boot disk 준비
- UART booting : 로컬에 저장되어 있는 uboot 이미지 파일로 앞서 만든 boot disk를 지정하여 포고플러그 부팅
- 포고플러그 리눅스 상에서 uboot 복구


1. Boot Disk 준비 과정은 리눅스 설치 방법과 다를 것이 없다.

rootfs 전개: http://forum.doozan.com/read.php?2,12096

요약하면 아무 linux 컴퓨터(포고플러그 순정 os도 가능함)에서 상기 플래시 메모리(usb, sd카드)를 마운트한 후 rootfs 압축 파일을 풀어주면 된다. 난 포고플러그는 답답해서 virtualbox에서 슥삭..

이 때 /etc/fstab에는 마운트 옵션을 아래처럼 지정한다.

<file system> <mount point> <type> <options>                       <dump> <pass>
LABEL=rootfs   /             ext3    defaults,nofail,noatime,nodev   0      1

ext4도 지원한다고는 하는데, ext3를 추천하더라. 그래서 ext3 사용하기로..

Debian 부팅 후 uboot과 uboot 변수를 갱신해야하므로, 최신 uboot 설치 파일을 미리 받아두었다.

그리고 시리얼 콘솔로 uboot만 달랑 띄워놓고 uboot 변수를 수정하는게 녹녹치 않아서 부팅 디스크의 /boot/uEnv.txt 파일에 주요 uboot 변수를 적어두었다.

bootdev=mmc     (별 의미 없다)

device=0:1


devices=mmc usb ide  (부팅 디스크 스캔 순서인데, 속도가 매우 빠르기 때문에 큰 의미 없음)


disks=0 1


usb_ready_retry=15


dtb_file=/boot/dts/kirkwood-pogoplug_v4.dtb    (기종에 맞게 변경필요)


load_uimage_addr=0x800000


load_initrd_addr=0x1100000


load_dtb_addr=0x1c00000


load_uimage=echo loading uImage ...; load $bootdev $device $load_uimage_addr /boot/uImage


load_initrd=echo loading uInitrd ...; load $bootdev $device $load_initrd_addr /boot/uInitrd


load_dtb=echo loading DTB $dtb_file ...; load $bootdev $device $load_dtb_addr $dtb_file


scan_disk=echo running scan_disk ...; scan_done=0; setenv scan_usb "usb start";  setenv scan_ide "ide reset";  setenv scan_mmc "mmc rescan"; for dev in $devices; do if test $scan_done -eq 0; then echo Scan device $dev; run scan_$dev; for disknum in $disks; do if test $scan_done -eq 0; then echo device $dev $disknum:1; if load $dev $disknum:1 $load_uimage_addr /boot/uImage 1; then scan_done=1; echo Found bootable drive on $dev $disknum; setenv device $disknum:1; setenv bootdev $dev; fi; fi; done; fi; done


set_bootargs=setenv bootargs console=ttyS0,115200 root=LABEL=rootfs rootdelay=10 $mtdparts $custom_params


bootcmd_exec=run load_uimage; if run load_initrd; then if run load_dtb; then bootm $load_uimage_addr $load_initrd_addr $load_dtb_addr; else bootm $load_uimage_addr $load_initrd_addr; fi; else if run load_dtb; then bootm $load_uimage_addr - $load_dtb_addr; else bootm $load_uimage_addr; fi; fi


bootcmd=run scan_disk; run set_bootargs; run bootcmd_exec

시리얼 콘솔 상에서는 부팅 초기에 이 파일을 읽어오는 설정만 입력할꺼다. 환경변수 하나 당 한 줄인데, 어디서 줄바꿈이 되는지 블로그 상에서 알아보기가 어려워서 일부러 한칸씩 띄웠으니, uEnv.txt에 복사할 때 빈 줄은 깔끔하게 삭제.


2. UART booting

안타깝게도 booting tool(kwboot)이 Linux용이다. 후다닥 virtualbox에 debian 64bit를 깔았다.
부팅 절차는 아래와 같다.

- kwboot, 최신 uboot을 다운받아 한 디렉토리 내에 압축을 푼다.
  : 각각 2017.08.03 기준 최신버전을 첨부함. (파일명 kwboot-tool.tar.gz , uboot.2016.05-tld-1.pogo_v4.bodhi.tar)

- boot disk를 포고 플러그에 장착한다

- UART booting 명령 실행

# ./kwboot -t -B 115200 /dev/ttyUSB0 -b uboot.2016.05-tld-1.pogo_v4.mtd0.kwd -p

- 전원 plug 삽입

정상적으로 진행된다면 아래 처럼 이미지가 로드되어야 한다.

# ./kwboot -t -B 115200 /dev/ttyUSB0 -b uboot.2016.05-tld-1.pogo_v4.mtd0.kwb -p
Sending boot message. Please reboot the target...|  (이 단계에서 전원 연결)
Sending boot image...
  0 % [......................................................................]
  1 % [......................................................................]
  3 % [......................................................................]
  5 % [......................................................................]
  6 % [......................................................................]
  8 % [......................................................................]
 10 % [......................................................................]
 11 % [......................................................................]
 13 % [.........
생략..

U-Boot 2016.05-tld-1 (Jun 12 2016 - 13:41:47 -0700)
Pogoplug V4

SoC:   Kirkwood 88F6192_A1
DRAM:  128 MiB
WARNING: Caches not enabled
NAND:  128 MiB
MMC:   kwsdio: 0
In:    serial
Out:   serial
Err:   serial
Net:   egiga0
No link on egiga0
ping failed; host 192.168.0.17 is not alive
Hit any key to stop autoboot:  5

Hit any key to stop autoboot: 카운터가 사라지기 전에 재빨리 아무 키나 눌러서 uboot 콘솔로 진입하자. 딴짓 하다가 타이머 놓치면 포고플러그 kwboot 명령어 부터 다시 시작.. uboot 진입 시점에 초록색 램프가 깜빡이기 시작하니 참고.


아래 환경변수가 부팅 디스크에서 uEnv.txt를 로드하는 기능이다. 한줄씩 착실히 입력.

setenv devices 'mmc usb ide'

setenv uenv_addr '0x810000'

setenv uenv_init_devices 'setenv init_usb "usb start";  setenv init_ide "ide reset";  setenv init_mmc "mmc rescan"; for devtype in $devices; do run init_$devtype; done;'

setenv uenv_read 'echo loading envs from $devtype $disknum ...; if load $devtype $disknum:1 $uenv_addr /boot/uEnv.txt; then setenv uenv_loaded 1; fi'

setenv uenv_read_disk 'if test $devtype -eq mmc; then if $devtype part; then run uenv_read;  fi; else if $devtype part $disknum; then run uenv_read; fi;  fi'

setenv uenv_load 'run uenv_init_devices; setenv uenv_loaded 0; for devtype in $devices;  do for disknum in 0; do run uenv_read_disk; done; done;'

setenv uenv_import 'echo importing envs ...; env import -t $uenv_addr $filesize'

setenv bootcmd_uenv 'run uenv_load; if test $uenv_loaded -eq 1; then run uenv_import; fi'


uEnv.txt 로드

run bootcmd_uenv


제대로 되었다면 아래와 유사한 메시지가 반겨줘야 한다.

Partition Map for MMC device 0  --   Partition Type: EFI

Part    Start LBA       End LBA         Name
        Attributes
        Type GUID
        Partition GUID
  1     0x00000800      0x01dd6fff      ""
        attrs:  0x0000000000000000
        type:   0fc63daf-8483-4772-8e79-3d69d8477de4
        guid:   090a98f0-2bb0-4d3a-84a8-0fe2ed18f43f
loading envs from mmc 0 ...
1466 bytes read in 1030 ms (1000 Bytes/s)


두근두근 부팅!

boot


3. Uboot 복구

순정 상태에서 최신 Uboot과 환경변수를 NAND에 flashing 하는 절차와 완전 동일하다. 순정 os가 아닌 Debian에서 진행한다는 것만 유일하게 다름.
참조: 포고플러그: 리눅스 설치를 위한 uboot 업그레이드