President Moon


요새 뭐 좀 비싼 카메라 메고 댕김서 펜대들고 설치는 놈들,
혓바닥이 걸레 쪼가리인건지 주둥아리로 쓰레기를 토해 내던데,

내가 뽑은 대통령이다.
건들지 마라.

무조건 지지

TCC8935 based Android IPTV hack/reverse-engineering

오~~ 요번글 제목도 괜찮다.
재활용 쓰레기장서 아래 그림처럼 희한하게 생긴걸 하나 주웠는데 인터넷TV 셋톱박스라는 구만.
근데 외부에 버튼 하나 없다.
아마 적외선 리모컨으로 조작하는가 본데 리모컨이 없으니 켜보지도 못하겠다.
모델명으로 검색해 봐도 안드로이드 기반의 IPTV라는거 말고는 당최 쓸만한 자료가 나오질 않는다.
제작사 홈페이지도, 공식 펌웨어도 못찾겠다.




[FIG.1 KM1100 Amway(Daum) IPTV mini]

[FIG.2 Main board]

[FIG.3 Component-side]

[FIG.4 Bottom-side]


  뭐 들어있나 배를 따봤다. 내부가 썰렁하다.
  CPU하나, 1GB DDR메모리, WIFI + Bluetooth 칩하나, 그리고 4G짜리 마이크로 SD카드 하나 달려있다. NAND나 NOR가 없는것으로 보아 SD로 부팅하는거 같다.
  CPU 모델명이 TCC8935라고 써있는데 검색해 보니 1GHz짜리 ARM Cortex A9프로세서다. 거기에 듀얼코어다. 우와... 메모리도 1GB에 안드로이드를 올릴 수 있다. 우와...
  안드로이드 함 올려볼까 하고 자료를 뒤적거려 봤다. 해당 칩으로 개발이 가능한 소프트웨어 패키지가 유출된적이 있었는데 지금은 구할 수가 없다.

  I've got an Android based IPTV H/W from recycle trash can that has a TCC8935 marked 1GHz ARM Cortex A9 processor, an 1GB DDR memory, an WIFI + Bluetooth chip and a 4GB micro-SD card, refer to [FIG.1], [FIG.2], [FIG.3] and [FIG.4]. It seems to be booted with micro-SD since there is neither NOR nor NAND.
  I could not turn the power it on because of absence of IR remote controller, so couldn't check it's ok or not (There is no hardware power botton).
  I found a web page that commenting about the TCC8935 and leaked development SW package but the leaked file has been gone.




  해당 웹페이지 글 내용으로만 봐서는 저것만 있으면 모든게 술술 풀릴듯 한데 아쉽게도 현재는 구할 수가 없다. 어쩔수 없이 삽질을 시작 했다.
  기본적으로 SD부팅을 하는데 SD카드를 제거하면 USB 부트모드로 진입가능하고 OS에서 신규 디바이스로 인식한다. USB 부트모드를 활용하면 될듯 하여 자료를 뒤져 봤으나, USB 부팅에 대한 자세한 내용은 역시 찾을 수가 없다.
  VTC라고하는 드라이버와 FWDN이라고 하는 SW를 가지고 펌웨어 업데이트등 조작이 되는듯 한데, 역시나 FWDN SW에 대한 USB프로토콜등 자세한 관련내용이나 자료도 없다.
  CPU벤더가 중국회사인줄 알았는데 Telechips라고 하는 한국에 있는 회사였다. 회사 홈페이지에 가봐도 의무적으로 공개해야하는 포팅된 리눅스 커널이외 쓸만한 자료는 없었다.
  개발자의 접근을 용이하게 해주면 더 잘 팔릴텐데...
  여튼, 도움이 될만한 자료가 거의 전무하다.
  보드에 TP가 몇개 보이길레 몇 군데 찔러보고 UART 핀을 찾아내고, 힌트가 될 만한 VTC/FWDN을 붙잡고 시작해봤다.
  구해진 VTC드라이버는 구버전이라 TCC8935를 지원하지 않는다. VTC드라이버 패키지에서 '*.ini' 파일을 찾아 TCC8935의 USB VIP/PID(0x140E/0xB098)를 쑤셔넣고 강제로 드라이버를 인식 시켰다.
  FWDN SW를 구동하면서 USBpcap(http://desowin.org/usbpcap)으로 USB패킷을 모조리 수집한 후 USB bulk-in/out 패킷을 분석하였다. 패킷 분석을 통해 내용을 대충 알아내고, libusb를 사용해 CPU에 코드를 쑤셔넣어 가면서 테스트 후 자작한 부트로더를 올릴 수 있었다.
  먼저 USB 패킷 크기는 512바이트이고, 2종류로 구성된다. 하나는 헤더 패킷, 두번째는 칩에 다운로드할 펌웨어 바이너리 패킷으로 구성된다. 헤더 패킷 포멧은 아래와 같다.

  There are some TPs at the board, and after digging, I found UART pin from the board. When I plugged the micro USB cable for power on, I could receive the bootloader and linux/Android kernel boot messages. Yes, the board is OK, but it's booted again and again. Probably the file system has been crashed.
  It's hard to find useful information about the development or firmwares on the net. I've googled for a few days but no luck without outdated VTC driver and FWDN for Windows.
  That VTC driver I've got was not support the TCC8935. Moreover there is no detailed user manual for the FWDN. After modification of the '*.ini' file, I could install the device driver with outdated-VTC driver compulsorily in Windows.
  I decided to analyze the USB packet with USBpcap(http://desowin.org/usbpcap).
  After digging with the USB packets for the FWDN and compulsory installed VTC driver through USBpcap and test code injection, I've found out working USB protocol format. First of all, USB bulk-in/out size is 512byte.
  The USB transaction is seperated into two parts, one is header and the other is main body for binary data transfer. USB header packet is like below.


  +--------------------------+
  | 32bit header key-code    | -> 0xf0000000, 0xf0000001
  +--------------------------+
  | 32bit download size      | -> download binary size in byte
  +--------------------------+
  | 32bit start address      | -> jump address after download
  +--------------------------+
  | 32bit download address   | -> download address
  +--------------------------+


  헤더 전송 이후 바이너리 데이터를 USB로 전송하면 된다. 코드로 구현하면 아래와 같다.

  After sending the USB header, you can send the binary code. This sequence is same as older TCC7xx or TCC8xx series but the header is little different.


  ---------------------------------------------------------
  unsigned int head[512>>2]= { 0, };
  ...
  p_dev= dev_open();  // device open
  ...
  // send header
  head[0]= key_code;
  head[1]= bin_size;
  head[2]= start_addr;
  head[3]= load_addr;
  usb_bulk_write( p_dev, 0x01, (char*)&head[0], 512, 500 );
  usb_bulk_read( p_dev, 0x82, (char*)p_rx, 512, 500 );
  ...
  ...
  // send binary
  usb_bulk_write( p_dev, 0x01, (char*)p_bin, bin_size, 5000 );
  usb_bulk_read( p_dev, 0x82, (char*)p_rx, 512, 500 );
  ...
  ---------------------------------------------------------
  key_code  : 0xf0000000 or 0xf0000001
  bin_size  : binary size in byte
  start_addr: jump address after download
  load_addr : download address
  p_dev     : USB device handle
  512       : USB bulk-in/out size
  500       : timeout in ms


  USB bulk-out이후 반드시 bulk-in을 읽어줘야 정상적으로 동작 되었다.
  헤더의 key-code가 FWDN 패킷 분석시 0xf0000000, 0xf0000001, 0xf0000006이 식별되었다. key-code가 0xf0000000일 경우 start address로 명시된 주소지를 콜한다. 무조건 분기가 아니고 함수 호출 형태이다. key-code가 0xf0000001일 경우 start address를 콜하지 않는다. 그냥 메모리로 다운로드만 한다. 패킷 분석시 0xf0000006도 있었는데 이건 뭔지 모르겠다 (메모리 읽기?). 여기서 중요한게 0xf0000000와 0xf0000001를 잘 사용하는 것이다.
  CPU 부팅시 DDR 메모리는 초기화가 되어 있지 않으므로 DDR메모리로 커널이나 부트로더등을 다운로드 할 수가 없다. 이때 0xf0000000을 이용해 내부 램에 DDR을 초기화 하는 코드만 전송하고, 두번째는 0xf0000001을 이용해 리눅스 커널을, 세번째는 다시 0xf0000000을 적용하고 부트로더를 전송후 부트로더로 점프하면 된다.
  USB 부트모드에서 CPU로 다운로드하기 위한 프로그램(usb_loader.exe)을 만들었다. 이 글 마지막에 드라이버와 프로그램 다운로드 링크를 걸어 둔다.
  자작한 usb_loader.exe 프로그램은 '-h', '-l', '-s', '-f'의 옵션 사용이 가능하다.

  There are several header key-code, 0xf0000000, 0xf0000001, 0xf0000006. Key-code 0xf0000000 is for download firmware and call the address that has been specified by start address in the header. I figured out that the CPU calls like a C-function call, it's not an unconditional JUMP with 0xf0000000 header key-code. Key-code 0xf0000001 is for just download, nothing happened after download with 0xf0000001 header key-code. There was 0xf0000006 key-code at the captured USB packet but I couldn't figured out what is this for. (memory read?)
  Calling usb_bulk_read() was mandatory after usb_bulk_write() in my test and always 4byte is returned with usb_bulk_read().
  I've made my own USB downloader(usb_loader.exe) for the TCC8935 from my USB packet digging result. It's uses libusb.
  You can download my USB downloader at the end of this text.
  The '-h', '-l', '-s', '-f' options are available for this program.


  -h: 0xf0000000 or 0xf0000001
  -l: download address
  -s: jump address after download
  -f: binary file


  자작한 프로그램으로 아래와 같이 사용 할 경우 리눅스와 부트로더가 DDR에 적재되고 부트로더로 점프할 수 있다.

  You can boot the TCC8935 CPU with bootloader/linux like below sequence. 4byte returned data is always 0x00000000 with 1st and 2nd download, but 0xffffffff after 3rd download.

  // DDR initialization code injection
  c:\>usb_loader.exe -h0xf0000000 -l0x10008000 -s0x10008000 -fddr_init.bin
  // wait 100~500ms
  // linux kernel injection
  c:\>usb_loader.exe -h0xf0000001 -l0x80008000 -s0x80008000 -fImage.bin
  // wait 100~500ms
  // download bootloader and jump to bootloader
  c:\>usb_loader.exe -h0xf0000000 -l0xbff00000 -s0xbff00000 -fbootloader.bin


  ddr_init.bin에는 DDR초기화 코드만 들어 있다. DDR초기화 이후 그냥 리던하면 된다. ddr_init.bin에서도 CPU 모든 레지스터에 접근이 가능하기 때문에 테스트 코드 같은거 집어 넣고 돌려봐도 된다. 리눅스 커널 다운로드등 다음 스텝으로 넘어 가려면 그냥 DDR 초기화 함수에서 리턴하면 된다. 이후 리눅스 커널을 0xf0000001로 다운로드만 하고, 다시 0xf0000000로 부트로더를 다운로드하면 부트로더 동작이 가능하다.
  메모리에 커널과 부트로더가 있으니, 부트로더에서 ATAG만들고 커널로 점프하면 된다.
  Telechips 홈페이지에서 구한 linux-3.4.35 커널을 빌드하고 테스트 해봤는데 일단 start_kernel()까지 진입은 가능했다. 부팅은 되는데 'Calibration delay loop...'에서 멈춘다. 추적해 보니 jiffies가 변경되기를 기다리는 루틴이 있는데 거기서 멈춘다. 타이머 인터럽트 서비스가 되지 않는다. 다른 삽질이 기다리고 있는듯 하다.

  The ddr_init.bin is for DDR initialization, if you finish the DDR-init. function just return, then you can proceed to next step. The next step is just injection the kernel with 0xf0000001 header key-code into the DDR. Now you can jump to the bootloader after 3rd download, then you can call linux kernel with ATAG.
  I've tested with linux-3.4.35 from the Telechips homepage. I could reached start_kernel() at my initial test but hang on 'Calibration delay loop...' message. It seems to be not serviced timer interrupt since the kernel stucked at waiting code for jiffies count.




[    0.000000] Booting Linux on physical CPU 0
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.4.35 (root@kali) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0) ) #45 SMP PREEMPT Tue Dec 12 17:00:18 KST 2017
[    0.000000] CPU: ARMv7 Processor [412fc09c] revision 12 (ARMv7), cr=10c53c7d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] Machine: m805_893x
[    0.000000] Memory policy: ECC disabled, Data cache writealloc
[    0.000000] L310 cache controller enabled
[    0.000000] l2x0: 16 ways, CACHE_ID 0x410000c6, AUX_CTRL 0x70150001, Cache size: 524288 B
[    0.000000]     pll_0:  cpu clock source
[    0.000000]     pll_1:  500000 kHz (Fixed)
[    0.000000]     pll_2:  0 kHz (Fixed)
[    0.000000]     pll_3:  audio clock source
[    0.000000]     pll_4:  0 kHz (Fixed)
[    0.000000]     pll_5:  0 kHz (Fixed)
[    0.000000] div_pll_0:  cpu clock source
[    0.000000] div_pll_1:  0 kHz (Fixed)
[    0.000000] div_pll_2:  0 kHz (Fixed)
[    0.000000] div_pll_3:  audio clock source
[    0.000000] div_pll_4:  0 kHz (Fixed)
[    0.000000] div_pll_5:  0 kHz (Fixed)
[    0.000000]       xin:  24000 kHz (Fixed)
[    0.000000] clocktable initialized
[    0.000000] TCC clock driver initialized
[    0.000000] PERCPU: Embedded 8 pages/cpu @c120b000 s11200 r8192 d13376 u32768
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 260096
[    0.000000] Kernel command line: vmalloc=480M console=ttyTCC0,115200n8 initrd=0xB0400000,0x00061B28 ramdisk=8192 root=/dev/ram0
[    0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[    0.000000] Memory: 1024MB = 1024MB total
[    0.000000] Memory: 1028852k/1028852k available, 19724k reserved, 507512K highmem
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
[    0.000000]     vmalloc : 0xe1800000 - 0xff000000   ( 472 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xe1000000   ( 528 MB)
[    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
[    0.000000]     modules : 0xbf000000 - 0xbfe00000   (  14 MB)
[    0.000000]       .text : 0xc0008000 - 0xc066b28c   (6541 kB)
[    0.000000]       .init : 0xc066c000 - 0xc069cbc0   ( 195 kB)
[    0.000000]       .data : 0xc069e000 - 0xc0878d78   (1900 kB)
[    0.000000]        .bss : 0xc0878d9c - 0xc0a01730   (1571 kB)
[    0.000000] SLUB: Genslabs=11, HWalign=64, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
[    0.000000] Preemptible hierarchical RCU implementation.
[    0.000000] NR_IRQS:195
[    0.000000] sched_clock: 32 bits at 12MHz, resolution 83ns, wraps every 357913ms
[    0.000000] Initialize the clocksource device.... rate[24000000]
[    0.000000] Console: colour dummy device 80x30
[    0.000000] [UART00] setting ulcon: 00000003, umcon: 00000002, brddiv to 0, baud 115200, uart_clk 0
[    0.000000] console [ttyTCC0] enabled
[    0.278620] Calibrating delay loop...

[FIG.5 Heat-sink/UART-port modification]

  KEY      : GPE[16], USB boot when power on with pressed-down
  LED      : GPF[3]
  IRDA     : GPG[17]
  TP17     : GND
  TP16     : GPF[26] (UART-RX[14])
  TP15     : GPF[25] (UART-TX[14])
  TP14     : nRESET
  SD-CLK   : GPD[31]
  SD-CMD   : GPD[30]
  SD-D[3:0]: GPD[26,27,28,29]

TCC8935 USB downloader driver: download
TCC8935 USB downloader: download
(Tested at Windows 7 x64)

2017/07/29 ~ 08/06 체코여행


























중요한 맥주 정보부터.
체코에서 필스너우르켈 생맥, 코젤블랙(다크) 생맥, 양조장이 있는 식당에서 먹은 이름모를 생맥을 마셔보고, 마트에서 판매하는 필스너우르켈 병맥, 스타로프라멘(언필터) 병맥, 코젤 병맥, 감브리너스 병맥, 부드바(버드와이저) 병맥, 이름이 기억나지 않는 2L 피쳐맥주 그리고 그 외 수많은 맥주들을 마셔 봤다. (체코 체류 기간 내내 맥주에 쩔어 살았음)
그 중 내 입맛에 가장 잘 맞았던 맥주 순위는 다음과 같다.

1. 스타로프라멘(언필터) 병맥 (생맥을 못 마셔본게 너무 아쉬움, 0순위가 되지 않을까...)
2. 부드바(버드와이저) 병맥, 필스너우르켈 생맥
3. 이름이 기억나지 않는 2L 피쳐맥주, 코젤블랙(다크) 생맥

처음들어본 이름인 스타로프라멘이 가장 좋았다. 반드시 언필터를 사야 한다.
스타로프라멘 생맥을 파는 식당이 따로 있는데 찾지 못해 생맥 맛을 보지 못한게 너무 아쉽다.
우리나라 맥주 전문점에서 마셔본 헤페바이젠 병맥과 맛이 비슷하다.

버드와이저(부드바)가 미국 맥주인줄 알았는데 원래 체코 맥주라고 한다. 미국에서 상표를 무단 사용했댄다. 스타로프라멘 다음으로 좋았다.

체코라는 곳을 가보기전에 필스너우르켈 캔맥을 우리나라 마트에서 사다 먹어본적 있는데 그 특유의 쌉쌀한 맛이 나에게는 맞지 않았다. 체코에서 마셔본 필스너우르켈 생맥과 병맥은 우리나라에서 마셔본 캔맥과 맛이 달랐다. 특유의 씁쓸한 맛이 생맥은 전혀 없었고, 병맥은 나에게도 괜찮은 수준이었다.

체스키 크룸로프에서 1박 할 때 동네 작은 매점에서 2L짜리 피쳐 맥주를 사서 먹었는데 그 맛이 괜찮았다. 이상하게 생긴 아저씨가 예사롭지 않은 표정으로 맥주를 들이키는 이미지가 있었는데 이름이 도무지 기억나지 않는다. 맛은 코젤블랙과 비슷한 류인데, 약간 카라멜 향이 나는듯했다.

코젤블랙은 국내 블로그에 많이 소개되어 기대했으나, 2잔 정도 마시면 나에겐 살짝 물리는 맛이었다. (쓴맛을 저감하기 위해 설탕이 들어간다고 하는데 그것 때문인지...)


체코하면 돼지 족발요리(이름이 기억 안남)가 또 소개가 많이 되길레 먹어 봤지만, 나는 개인적으로 체코 소고기 스테이크가 가장 맛이 좋았다. 피가 줄줄 흐르는 미디움 레어의 살덩어리를 쓱쓱 잘라 소금과 후추만 살짤 뿌리고 입에 넣으면 고기가 녹는다.
스테이크소스도 꽤 맛있는 편에 속함에도 불구하고 스테이크소스보다 그냥 소금과 후추를 강력하게 추천한다. 소고기 특유의 고소한 맛이 이렇게 풍미스럽게 나는건지 처음 알았다.
미국본토나 괌에서 먹어봤던 스테이크보다 훨씬 맛있고 가격도 저렴하다.


물가가 참 괜찮다.
감탄을 하며 먹었던 소고기 스테이크는 한접시에 15,000~20,000원 수준이다.
5명 가족이 이동을 해야해서 숙박은 패밀리룸을 주로 얻었는데 보통 150,000~190,000원 정도 였던 걸로 기억한다. 자동차 렌트도 하루에 4~5만원 정도였다.
500ml 스타로프라멘이나 필스너우르켈 병맥이 700~900원, 식당에서 먹는 코젤블랙 생맥이 1,500~2,000원 수준이다. 마트에 500원짜리 병맥도 많은데 맛도 나쁘지 않다.
맥주를 너무 많이 먹었는지 지금은 물만 닿아도 이가 시리다.
으으...


개인적으로 사람들 북적북적대고 복잡한곳 보다 한가로운 곳을 더 선호하는 편인데, 그래서 그런지 프라하보다 체스키 크룸로프가 더 나았다. 아침일찍 프라하 유명한 거리로 나가보면, 특히 가로수 주변이나 구석진 곳엔 오줌 지린내가 진동을 한다.
체스키 크룸로프에서 1박 밖에 못한게 좀 아쉽다.
그 곳 한적한 저녁 거리에 조그마한 펍에서 생맥주 한 잔 해볼껄.. 하는 생각이 든다.

2017/02/04 ~ 02/10 미국여행

















가족들 데리고 라스베이거스와 로스엔젤레스를 다녀 왔다.
올 초에 다녀왔는데 이제야 기록을 올리는군.
차를 빌렸는데 운전한 기억밖에 없을 정도로 땅덩어리가 참 많이 넓었다.
뻥좀 보태서 1시간 내내 조향이 필요 없을 만큼 쭉~~, 그냥 앞으로 쭈~~욱 뻗은 직선도로.

나도 사이다

인터넷 게시판 들락거리다 보면 사이다 이야기가 가끔 나온다.
아주 속 시원한 이야기.

나도 사이다.

'나는 돈이 없음' 으로 음슴체

- 전세집에 세들어 살다 타지역으로 이사를 감.
- 전세금은 모두 집주인으로 부터 받았으나 아파트 장기수선충당금을 집주인이 반환하지 않음 (아파트 장기수선충당금은 세입자가 지내는 동안 매월 관리비와 함께 납부한 다음 전세 계약 종료시 집주인이 세입자에게 반환 해야함).
- 이사 나간 후 몇 개월 수차례 전화를 하였으나 안받음, 나는 열받음.
- 평소 법을 아주 잘지키며 사는 착한 사람이라 어떻게 해야 할 지 난감 했음.
- 구글 신께 문의 결과 민사소송을 해야 할 것으로 판단.
- 법을 모르는 사람이라 변호사를 고용해야 하나 고민함, 허나 나는 돈이 없음.
- 법원을 며칠 들락 거리며 혼자 민사소송 소장을 제출, 나 원고, 전 집주인 피고.
(소장 제출시 소송 일정 및 관련 내용에 대해 원고/피고에게 등기 우편 고지를 위해 송달료를 6~7만원 정도 납부해야 함, 소송이 종결되면 잔금은 환급 받을 수 있고, 지불된 금액은 피고에게 청구 할 수 있는 권리가 생김).
- 피고의 집주소가 명확치 않다고 보정명령(불확실한 내용에 대한 수정요청)을 법원으로 부터 받음 (앞서 지불한 송달료를 이용해 등기우편으로 법원에서 날아옴).
- 소송의 근거가 있으므로 3자(피고)의 주민번호를 이용해 현 거주지 파악 가능.
- 파악된 거주지로 보정자료 법원에 제출.
- 재판날짜 잡혔으니 법원에 출석하라고 법원에서 원고와 피고에게 등기우편을 보냄 (재판시간과 재판장 번호등 기재되어 있음).
- 재판일 법원에 가보니 TV에서나 보던 재판장에 입장함, 재판장 출석 여부를 위해 원고와 피고를 호출함, 피고 불출석 확인됨, 재판장 '원고승' 한마디 하고 재판 끝남, 퇴장.
- 재판장 대기실에 나같이 억울하게 돈 못받은 사람들의 재판을 기다리는 사람이 정말 많음.
- 며칠 후 재판 결과(판결문)가 원고와 피고에게 보내짐.
- '피고는 원고에게 원금 xx원 및 이에 대하여 xxxx년 xx월 xx일 부터 다 갚는 날까지 연 이율 20%의 비율로 계산한 돈을 지급하라', '소송비용은 피고가 부담한다' 라고 써있음.
- 판결 났으니 돈 갚으라고 피고에게 전화함, 또 안받음, 나는 또 열받음.
- 피고가 저렇게 배째고 있으니 나는 방법이 없음, 이 후 어떻게 해야할 지 모르겠음.
- 회사일도 바쁘고 해서 잠시 잊고 지냄, 가끔 피고에게 전화함, 계속 안받음, 나는 계속 열받음.
- 그러다 5년이 지나감.
- 그냥 둬선 안되겠다 싶어 방법을 또 구글신께 문의, 동산/부동산 압류를 해야 할 듯함.
- 무작정 법원을 또 다시 감.
- 법원 구조가 바뀌면서 무료법률 상담하는 방이 따로 생김, 5년전에도 무료법률상담 데스크가 있었는데 시끌벅적한 로비 한쪽 구석에 있었으며, 거의 자리에 사람이 없었음, 어쩌다 자리에 있을때 물어 보면 왜 '이런걸 나한테 왜 물어봐?' 짜증석인 표정과 말투로 대충대충 뭔 소린지도 모르게 대답함. 혼자 알아서 하고 말지.
- 여튼 새로 생긴 무료법률상담 방에 들어감, 대기표 뽑고 기다리면 법률 전문가와 한방에서 1:1로 상담이 가능함, 상담해주시는 분은 퇴직 후 상담 업무를 보고 있는 것으로 추정되며 상당히 친절하고 상세하게 알려줌
- 판결문이 있으니 역시 3자(피고)의 주민번호를 이용해 초본발급 가능, 현 거주지의 집 주인으로 거주하고 있음이 확인됨.
- 피고의 집(부동산)을 압류함 (법원에서는 압류라는 용어를 안쓰고 강제경매라고 함).
- 강제집행 신청시 비교적 큰 금액이 들어가는데, 송달료와 강제집행료 선납금임. 송달료는 아래에서 이야기하는 피고(채무자)가 공탁을 걸 경우 소모된 금액 만큼 공탁금으로 받을 수 있으며 소모된 금액 이외 잔금 또한 환급 가능하고, 강제집행료 선납금은 강제집행이 진행되지 않으면 거의 환급 가능하고 강제집행이 진행되면 강제집행시 소모된 비용을 제외하고 종료 후 나머지는 환급 가능함)
- 5년넘게 전화도 안받던 피고가 친히 나에게 전화를 다 해주심, 나 감격함.
- 정말 오래간만에 정말 듣고 싶었던 사람의 목소리를 들으며 그 동안 어떻게 살았으며, 무슨 일은 없는지, 건강은 어떤지, 밥은 먹고 다니는지, 안부도 물어가면서 대화하고 싶었으나, 나에게 버럭버럭 화를냄. 나는 말문이 막힘.
- '됐고, 나는 원금/이자에 소송에 들어간 비용까지 xxx만원은 받아야 경매 최소해 드립니다' 하니, 너무한거 아니냐며 또 소리를 버럭버럭 지름.
- '알아서 하세요' 하니 나중에 전화하겠다고 하여 통화 종료.
- 며칠 후 피고가 변제공탁을 신청함, 이 변제공탁 금액은 채권자(나)의 원금과 이자 그리고 강제경매를 위해 채권자가 소모한 모든 금액을 법원에 지불해야 변제공탁이 가능함 (변제공탁이 법원에 접수되고 인정되면 강제경매는 정지됨, 그러나 취소는 아님)
- 고로, 피고는 내가 강제경매를 위해 법원에 지불한 금액에 더불어 5년에 20%이므로 원금의 2배가 넘는 금액을 지출함.
- 온라인 상에서 변제공탁 환급 신청으로 모두 내 통장으로 넘어옴. 나는 기분이 좋음.
- 변제공탁 환급시 해당 금액으로 나의 피해가 모두 변제되지 않았다고 판단하여 '이의유보'의견 제출, 여전히 강제경매는 취소가 아닌 정지상태.
- 나는 5년전 판결문에서 명시한것 처럼, 원금/이자를 받았으니, 이제 추가로 소송비용을 모두 피고로 부터 받아야함. 다시한번 더 강조 하지만, 나는 법을 아주 잘 지키는 착한 사람임. 법원에서 받으라고 했으니 받아야함.

DOSBOX on ARM

오우... 요 글 제목은 좀 괜찮은거 같다.

이번 삽질은 ARM기반의 임베디드보드에 빌게이츠 할아버지가 만든 DOS (Disk Operating System) 운용이 가능하도록 하는 에뮬레이션 환경인 DOSBOX의 포팅이다.

DOS시절 (저는 아재가 아니라 DOS는 잘 모립니다)의 응용 프로그램을 그 당시 하드웨어 환경으로 모사하여 동작시켜주는 DOSBOX가 있다는걸 얼마전에 알았다. PC에서 잠깐 돌려보니 config.sys, autoexec.bat, himem, emm386 등등 거의 모든 환경이 그 당시와 유사하게 에뮬레이션 된다 (대단한데?).
스트라이크 커맨더를 돌리려고 640KB의 제한과 상위 메모리 1KB라도 더 빼내기 위해 고군분투 했던 일들.... 이 왜 기억 날까?...

DOS에서 돌아가던 고전 게임을 돌리기위한 DOSBOX사용이 대단히 활발하다.

나는 게임을 돌리기 위해서가 아니고, 그 시절 사용하던 ALL03A라는 Universal Programmer를 재활용 하기 위해 DOSBOX를 ARM 임베디드보드에 포팅하였다.
ALL03A는 EEPROM이나 GAL, PAL, CPLD, PIC등 프로그래밍 가능한 디바이스들의 프로그래머인데, IBM PC에 ISA 인터페이스 카드를 장착하고 DOS용 프로그램으로만 동작된다. 예전에 USB 기반으로 ISA 버스가 없는 PC에서 사용해 보려고 USB 어댑터 개발을 시도한 적이 있었는데 ALL03A SW를 모두 새로 다시 짜야하는 문제와 USB 패킷으로 일반 CPU BUS의 I/O를 흉내내는데는 속도의 한계가 있어 중단 되었다.

ALL03A SW는 ISA 버스를 통해 I/O를 수행하는데 현재의 PC환경에서는 이 I/O를 간편하게 핸들링 할 수 있는 포트가 없다.
그래서 ARM기반 임베디드시스템을 활용 하였다. 임베디드 보드를 활용 할 경우 GPIO를 OS에서 이용할 수 있으므로 이 GPIO를 이용하여 ISA BUS 기반으로 움직이는 데이터를 모사하면 된다. 보드에 임베디드 리눅스를 올리고, DOSBOX를 ARM용으로 포팅하여 실행 한다음, 거기에서 ALL03A SW를 구동시킨다. ALL03A SW가 ISA BUS에 접근하는 포트에 핸들러를 등록하고 해당 핸들러에서 리눅스 디바이스드라이버를 호출하여 I/O를 해결한다. 디바이스드라이버는 GPIO 포트를 이용하여, ALL03A SW의 I/O 호출에 대해 해당 핀의 물리적 동작을 직접 수행하는 구조이다. 말로 설명 할려니 복잡하군.

여튼, 작업 순서는 다음과 같다.

  - ARM 임베디드 보드에 임베디드 리눅스 포팅
  - ALL03A 하드웨어 인터페이스용 GPIO 인출 (ALL03A는 5V이므로 3.3V 레벨 쉬프팅 필요)
  - 인출한 GPIO에 대한 리눅스 디바이스드라이버 개발
  - DOSBOX를 ARM용으로 빌드, 이때 DOSBOX 소스를 수정하여 ALL03A SW가 접근하는 I/O어드레스에 리눅스의 GPIO 드라이버를 호출하는 핸들러를 개발 해야함

사용한 ARM 임베디드 보드는 예전에 리버스엔지니어링하여 리눅스를 올려놓은 S3C6410 네비게이션을 활용하였다.
DOSBOX에서 사용하는 640x200영역은 문제가 없으나 사용하지 않는 이외 영역은 화면 내용의 일부가 중복되거나 garbage데이터가 들어가는 모양이다. 손좀 봐야 겠다.


[S3C6410 기반 네비게이션 UB-5에서 DOSBOX 실행]


[ALL03A SW 파일 리스트]


[ALL03A의 EEP1.EXE 실행 화면]

다 만들고 돌려보니, 일단 ALL03A 하드웨어가 인식된다. 유후~~
ALL03A SW를 DOS박스에서 동작 시켜보니 일단 실행하는데는 문제가 없다.
그런데 ALL03A SW 실행시 특정 키 입력 대기 메뉴에서 ALL03A와 무수한 I/O가 수행되는데 이게 문제를 일으킨다. 단순 키보드 입력 대기 인데 알 수 없는 I/O가 발생되고 정상동작 되지 않는다. 이 부분은 왜그런지 모르겠다.

위 USB 어댑터 페이지에 http://matthieu.benoit.free.fr 링크에 보면 관련자료가 있는데, 그곳에서 구한, 일반 유저가 개발한 ALL03A SW에서는 그런 현상이 발견되지 않으며 정상 동작한다.
아마 오리지날 제작사에서 자체적으로 리버스엔지니어링등에 의한 카피 방지를 위한 코드가 아닐까 하는 의구심만 들 뿐이다.

요새 인공지능이 유행이라던데...

바둑 잘 두는 알파고가 그래 인기가 좋다는 구만.
딥러닝이 유행이라는 구만.

한 10여년전에 ANN (Artificial Neural Network)을 구현해서 써본적이 있었는데 그 때는 '딥러닝'이라는 용어가 없었던 걸로 기억한다.
로봇 구동부의 백레시를 보상해 주기 위해 BPANN (Back Propagation ANN)을 구현하고 Rigid Body 물리엔진과 연동해서 시뮬레이션 해봤었는데 기가 막히게 학습도 되고 결과도 잘 나왔었다. 문제는 학습이 진행되는 동안 로봇에 무리가 가는 동작이 많아 시뮬레이션만 하고 직접 로봇에 적용 하지는 못했었다.
사람처럼 자빠지고 깨지고 하면서 에러가 역전파되어 학습이 되지만, 로봇은 사람처럼 자가치유 능력이 없어 학습 될 때까지 깨지고 부서지는거 고치느라 일 다본다.
실제 로봇 제어에는 못쓰겠네... 하고는 딱히 쓸 일이 없어서 그냥 잊고 지냈었다.

그렇게 잊고 지내다 최근 PID제어기로 쿵짝쿵짝 뭐 할게 있었는데, 처음에는 잘 되던게 시간이 갈 수록 시스템의 동역학 파라미터가 변하면서 (시변 시스템 이라고 하죠? 아마?) 제어 게인을 다시 튜닝해 줘야 하는 문제가 있어, 제어 게인을 자동으로 학습하면서 튜닝해 주기위해 오래전에 만들었던 BPANN 소스를 다시보게 되었다. 근 10년전에 내가 짜놓은 소스를 다시 보니 내가 왜 그렇게 짜놨는지 이해가 안된다. 인공지능을 다시 공부 해야 겠다.

우선 PID제어기의 제어 게인 (Kp, Ki, Kd)을 자동으로 학습 할 수있게 되는지 테스트를 해봤다. 인터넷에 돌아댕기는 ANN의 학습기능을 이용한 자동 PID 게인 튜닝, On-Line PID 튜닝등 논문 몇 개 뒤져보고, 옛날에 만들어 놓은거 다시 손좀 보고해서 간단하게 전기식 모터의 위치 서보제어 시뮬레이션에 BPANN을 적용 시켜 돌려 봤다.
전기모터의 동역학 파라미터 (직류저항, 코일 인덕턴스, 회전자모멘트 등등)와 기어의 동역학 파라미터들을 이용해 시뮬레이션 물리엔진 만들고, 거기에 PID 제어기 물리고, 학습을 위해 BPANN 연동 시키고 등등...


위 그래프가 간이 형태로 되는지 확인해본 결과다.
300W정도 되는 BLDC모터에 200:1기어를 달고 있는 시스템을 시뮬레이션 하고 거기에 PID제어기를 물린다음, BPANN을 연동 시켜 On-Line형태로 제어 게인을 스스로 학습하도록 만들었다. 빨간색이 10도와 0도 스텝 위치 명령이고 녹색이 모터가 추종한 위치 응답 곡선이다. 최초 스텝 명령에 대해 큰 오버슈트, 언더슈트가 있으나 계속 학습되면서 나아진다.
명령 추종이 될까 했는데 신기하게 위치제어가 가능한 게인 값들로 학습되었다.
BPANN적용하기 전 손으로 튜닝해 봤는데 시간도 많이 걸리고 상당히 지루한 작업이었다.