-
Notifications
You must be signed in to change notification settings - Fork 1
/
search.xml
1107 lines (1107 loc) · 147 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>샤오미 WiFi 증폭기 Pro 열어보기</title>
<url>/2020/07/19/xiaomi-wifi-extender-pro/</url>
<content><![CDATA[<h1 id="발단">발단<a class="header-anchor" href="#발단"></a></h1>
<p>사실 증폭기 Pro는 한참 전부터 눈독을 들이고 있던 모델이었습니다. 실사용하려는 목적은 전혀 아니었고, 생긴 게 앙증맞고 예쁘니 여기다 OpenWrt를 올리면 금상첨화겠다, 라는 생각이었습니다.</p>
<p>제품을 구하기 전에 미리 하드웨어 정보를 알 수 있으면 좋을 텐데, 이 모델의 내부 사진을 찾기가 쉽지 않네요. 가끔씩 생각날 때마다 찾아보길 반복하다가 2019년 8월 말에 운좋게 <span class="exturl" data-url="aHR0cHM6Ly93d3cuem5qLmNvbS9uZXdzLzM3NDQuaHRtbA==">분해기<i class="fa fa-external-link-alt"></i></span>를 하나 발견했습니다.</p>
<p>뒷면 스티커 아래에 나사구멍이 숨어있었군요. 게다가 보드엔 시리얼 포트까지 떡하니 나와있네요. 괜찮아 보이는데요? 마침 그때 알리에서 $11.5에 팔길래 만약 실패하더라도 큰 부담이 안 되겠다 싶어 바로 하나 주문했습니다.</p>
<p>…</p>
<p>지금 와서 보면 성급한 충동구매였는데… 정말 가격이라도 싸서 다행이었네요.</p>
<span id="more"></span>
<h1 id="분해">분해<a class="header-anchor" href="#분해"></a></h1>
<p>외관은 이렇게 생겼습니다.<br>
<img src="001.jpg" alt="외관"></p>
<p>뒷면 스티커를 과감히 떼면 나사구멍 하나가 드러납니다.<br>
<img src="002.jpg" alt="뒷면 스티커 뗌"></p>
<p>걸쇠의 위치입니다.<br>
<img src="003.jpg" alt="걸쇠 위치"></p>
<p>보드의 뒷면.<br>
<img src="004.jpg" alt="보드 뒷면"></p>
<p>보드의 앞면.<br>
<img src="005.jpg" alt="보드 앞면"></p>
<p>일단 먼저 SoC부터 확인해봅시다. 방열패드를 들어내니 칩 마킹이 보입니다.<br>
<img src="006.jpg" alt="SoC"></p>
<p>MT7628KN.</p>
<p><img src="007.png" alt="MT7628K"></p>
<p><span class="exturl" data-url="aHR0cHM6Ly93d3cubWVkaWF0ZWsuY29tL3Byb2R1Y3RzL2hvbWVOZXR3b3JraW5nL210NzYyOGstbi1h">MediaTek 제품설명<i class="fa fa-external-link-alt"></i></span>을 보면 내장 DRAM이 8MB라고 합니다. 8메가아아? 8메가짜리에 어떻게 OpenWrt를 올려요… 망했네요.</p>
<p>처음에 내부 사진을 봤을 때 별도의 RAM 칩이 보이지 않는다는 것에 주목했어야 했는데… 이제 와서 후회해봐야 늦었지만요.</p>
<p>이미 여기서 모든 희망이 사라져 버렸지만, 그래도 이왕 산 건데 시리얼 접속까진 한번 해보죠.</p>
<p><img src="008.jpg" alt="플래시"></p>
<p>플래시는 <span class="exturl" data-url="aHR0cHM6Ly93d3cubWFjcm9uaXguY29tL0xpc3RzL0RhdGFzaGVldC9BdHRhY2htZW50cy83NDY1L01YMjVMMTYwNkUsJTIwM1YsJTIwMTZNYiwlMjB2MS45LnBkZg==">MX25L1606E<i class="fa fa-external-link-alt"></i></span>로 2MB. 메모리가 이렇게 쪼끄만할 줄이야… 이쯤 되면 펌웨어가 리눅스가 아닐 가능성도 있겠지요.</p>
<h1 id="콘솔-접속">콘솔 접속<a class="header-anchor" href="#콘솔-접속"></a></h1>
<p>보드에 적힌 대로 핀 연결을 하고 115200 보율로 접속하니 익숙한 U-Boot 로그가 우리를 반겨줍니다.<br>
<img src="009.png" alt="콘솔1"></p>
<p>부팅이 끝나고 엔터를 치니 쉘이 열립니다.<br>
<img src="010.png" alt="콘솔2"></p>
<p>분명 평범한 busybox 쉘은 아니네요.</p>
<p><img src="011.png" alt="콘솔3"></p>
<p>리눅스 대신 <span class="exturl" data-url="aHR0cHM6Ly9rby53aWtpcGVkaWEub3JnL3dpa2kvRUNvcw==">eCos<i class="fa fa-external-link-alt"></i></span>를 쓴 모양입니다. (참고로 ipTIME의 몇몇 기종도 eCos를 사용합니다.)<br>
nvram에서 <code>bootdelay</code> 값을 조절하면 부트로더 쉘도 열 수 있겠죠?</p>
<p><img src="012.png" alt="콘솔4"></p>
<p>간단한 시스템 정보를 보거나,</p>
<p><img src="013.png" alt="콘솔5"></p>
<p>LED와 버튼을 테스트해볼 수 있습니다.</p>
<p>이런 거 말고는 별로 할 수 있는 게 없는 것 같네요. Buildroot를 잘 쓰면 좁은 메모리 공간에 리눅스를 꾸겨넣을 수 있을 것 같기도 하지만, 그렇게까지 써보고 싶은 건 아니라 이쯤에서 마무리하겠습니다.</p>
]]></content>
<categories>
<category>자유시간 프로젝트</category>
</categories>
<tags>
<tag>분해</tag>
</tags>
</entry>
<entry>
<title>ipTIME A9004M 공유기에 Windows XP 올리기</title>
<url>/2020/08/08/winxp-on-a9004m/</url>
<content><![CDATA[<p>※ 2021-01-18: 서두의 트윗은 아이디어의 원천에 대한 레퍼런스 목적으로 달아둔 것이고, 누군가를 비하하거나 조롱하기 위함이 아닙니다. 이 점을 분명히 하기 위해 서두 부분을 살짝 수정했습니다.</p>
<h1 id="계기">계기<a class="header-anchor" href="#계기"></a></h1>
<p>작년에 우연히 이 <span class="exturl" data-url="aHR0cHM6Ly90d2l0dGVyLmNvbS9sZ19vbGVkX3R2L3N0YXR1cy8xMTQ3MTE5ODIxMjAyNDE1NjE2">트윗<i class="fa fa-external-link-alt"></i></span>을 보게 되었습니다.</p>
<p>그때까진 공유기에 OpenWrt 외의 일반 리눅스 배포판을 올려볼 생각을 해본 적이 없어서, 공유기에 VNC 서버를 올린다는 생각이 제겐 상당히 신선하게 다가왔습니다.</p>
<p>만약 WRT1900ACS에서 VNC 서버를 돌릴 수 있다면 충분히 사양이 좋은 ipTIME 기기에서도 가능할 것이라 생각했습니다. 예를 들어 NAS1dual에는 동일한 CPU와 더 큰 용량의 RAM이 들어가므로 단순히 연산성능으로만 봤을 땐 WRT1900ACS에 못지않다고 볼 수 있겠지요.</p>
<p>그래도 똑같은 플랫폼에서 똑같은 걸 따라하는 건 재미가 덜할 것 같고, ipTIME 공유기 중에서 충분히 성능이 좋은 A9004M에서 시도해보기로 했습니다.</p>
<span id="more"></span>
<h1 id="A9004M-위에-OpenWrt">A9004M 위에 OpenWrt<a class="header-anchor" href="#A9004M-위에-OpenWrt"></a></h1>
<p>일단 OpenWrt부터 올려봅시다.</p>
<img src="/2020/08/08/winxp-on-a9004m/002-banner.png" class="">
<p>OpenWrt에선 X11이나 VNC 같은 GUI 관련 패키지를 제공하고 있지 않기 때문에, OpenWrt 바로 위에 VNC 서버를 올리는 건 쉽지 않을 것 같습니다.</p>
<p>정말 Debian을 올리려고 한다면 Armbian을 포팅하거나 debootstrap을 쓰는 방법도 있겠지만, 단순한 PoC를 위해 거기까지 손대는 건 좀 귀찮고, 다행히 Docker 패키지는 있어서 도커 컨테이너를 올리는 방향으로 가겠습니다.</p>
<p>OpenWrt 이미지를 빌드할 때 도커에 필요한 커널 모듈을 같이 포함해줍시다.<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> 만약 나중에 업스트림에서 A9004M을 공식 지원하게 된다면 이 과정은 필요없게 됩니다.</p>
<img src="/2020/08/08/winxp-on-a9004m/003-diffconfig.png" class="">
<p>한편 도커 패키지를 설치하고 이미지를 다운로드 받기에 128MB 내장 플래시는 너무나도 비좁습니다. extroot를 써서 루트 파일시스템을 외부 USB 메모리로 옮길 필요가 있습니다. <span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL2d1aWRlLXVzZXIvYWRkaXRpb25hbC1zb2Z0d2FyZS9leHRyb290X2NvbmZpZ3VyYXRpb24=">가이드<i class="fa fa-external-link-alt"></i></span>를 따라가면 어렵지 않게 할 수 있습니다.<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup></p>
<p>그리고 후술할 이유로 <code>/opt</code>에 마운트할 파티션이 따로 필요합니다.</p>
<img src="/2020/08/08/winxp-on-a9004m/004-df.png" class="">
<p>이제 도커를 설치할 준비가 되었습니다.</p>
<h1 id="Docker-위에-VNC-서버">Docker 위에 VNC 서버<a class="header-anchor" href="#Docker-위에-VNC-서버"></a></h1>
<p><code>opkg install docker-ce</code>로 패키지를 설치합니다. <abbr title="2020-08-08">현재</abbr> docker-ce 패키지는 arm, aarch64, x86_64 아키텍처에서만 지원됩니다. 아마 mipsel 기반인 MT7621에서도 가능할 것 같은데, 혹시 관심 있는 분이 계시다면 테스트 부탁드립니다.</p>
<img src="/2020/08/08/winxp-on-a9004m/005-docker-info.png" class="">
<p>도커의 기본 스토리지 드라이버는 overlay2이지만, <span class="exturl" data-url="aHR0cHM6Ly9sa21sLm9yZy9sa21sLzIwMTgvMS84Lzgx">커널 구현의 한계<i class="fa fa-external-link-alt"></i></span>로 OpenWrt의 overlay 루트 파일시스템 위에서는 작동하지 않습니다. 만약 위에서 <code>/opt</code>에 별도 파일시스템을 마운트하지 않았다면 overlay2보다 느리고 용량도 많이 차지하는 vfs를 사용하게 됐을 겁니다.</p>
<p>VNC 서버 이미지를 다운받고 컨테이너를 실행합니다.</p>
<img src="/2020/08/08/winxp-on-a9004m/006-docker-run.png" class="">
<p>작업이 완료되면 이제 외부에서 VNC 클라이언트나 웹 브라우저를 통해 VNC 서버에 접속할 수 있습니다.</p>
<img src="/2020/08/08/winxp-on-a9004m/007-novnc.png" class="">
<p>생각보단 반응속도가 좋습니다. 자원도 그리 많이 잡아먹지 않고요. 하지만 브라우저 같이 무거운 걸 켜면 느려집니다.</p>
<img src="/2020/08/08/winxp-on-a9004m/008-firefox.png" class="">
<h1 id="QEMU-위에-Windows-XP">QEMU 위에 Windows XP<a class="header-anchor" href="#QEMU-위에-Windows-XP"></a></h1>
<p>드디어 이 글의 제목을 실현할 차례입니다. 터미널에서 qemu를 설치하고 PC에서 미리 준비해온 디스크 이미지로 부팅하면…</p>
<p>짠.</p>
<img src="/2020/08/08/winxp-on-a9004m/009-winxp.png" class="">
<hr>
<p>덧: 이 글을 올리기 직전에 알게 된 건데, 이제 OpenWrt의 procd가 runc 역할을 할 수 있게 됐다고 합니다. (<span class="exturl" data-url="aHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvcGlwZXJtYWlsL29wZW53cnQtZGV2ZWwvMjAyMC1BdWd1c3QvMDMwNzQwLmh0bWw=">원문<i class="fa fa-external-link-alt"></i></span>) 서드 파티 패키지 없이도 컨테이너를 돌릴 수 있다니 좀 신기하네요.</p>
<img src="/2020/08/08/winxp-on-a9004m/010-uxc.png" class="">
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>도커를 본격적으로 사용할 거라면 <code>CONFIG_DOCKER_KERNEL_OPTIONS</code> 등도 켜주면 좋겠지만, 가상화에 꼭 필요한 커널 옵션은 이미 <span class="exturl" data-url="aHR0cDovL2dpdC5vcGVud3J0Lm9yZy9mY2I0MWRlY2Y2Yw==">켜져있어서<i class="fa fa-external-link-alt"></i></span> 그런지, 추가 옵션을 주지 않아도 제 목적에는 충분했습니다. <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>좋은 <span class="exturl" data-url="aHR0cHM6Ly93d3cubmVtb25laW4ueHl6LzIwMjAvMDcvNDAxNC8=">정리글<i class="fa fa-external-link-alt"></i></span>이 있어서 링크를 달아둡니다. <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content>
<categories>
<category>자유시간 프로젝트</category>
</categories>
<tags>
<tag>OpenWrt</tag>
<tag>Docker</tag>
</tags>
</entry>
<entry>
<title>국산 공유기에도 OpenWrt를 올릴 수 있을까</title>
<url>/2020/08/18/korean-home-router-survey/</url>
<content><![CDATA[<p>※ 2021-01-10: 정보 업데이트</p>
<h1 id="개괄">개괄<a class="header-anchor" href="#개괄"></a></h1>
<blockquote>
<p>⚠️ 이 글의 내용은 전적으로 제 좁은 경험과 얕은 조사에 기반한 것이고, 빠지거나 틀린 내용이 있을 수 있습니다.</p>
</blockquote>
<p>2021-01-10 기준으로 국내 회사에서 내놓은 인터넷 공유기 중에 이미 OpenWrt를 지원하거나 포팅이 유망해보이는 기종이 어떤 게 있는지 정리해보려고 합니다.<br>
기업용 AP나 라우터 쪽은 제가 잘 모르기 때문에 이 글에선 가정 및 SOHO용 공유기를 주로 다룰 겁니다.</p>
<span id="more"></span>
<hr>
<p>국산 공유기는 크게 두 종류로 나눌 수 있겠습니다: 통신사 공유기와 “사제” 리테일 공유기.</p>
<p>통신사 공유기라 하면 일반적으로 가정용 임대 공유기를 말하지만, 그 외의 것도 조금 있긴 합니다.<br>
리테일 공유기의 경우 예전엔 제조사 수가 꽤 많았지만, 지금은 ipTIME 외엔 대부분 정리되고 몇몇 군데만 남은 상황입니다.</p>
<p>리테일 공유기의 포팅 가능성은 대체로 SoC 제조사별 특성에 따라갑니다.</p>
<ul>
<li>Qualcomm Atheros: 포팅 잘 되고 작동도 잘 합니다. 무선 성능을 제대로 이끌어내기 위해선 정펌에서 따온 boardfile이 필요할 수 있습니다.</li>
<li>Ralink/MediaTek: 포팅 잘 되고 작동도 잘 합니다. 예전엔 무선 칩셋 드라이버에 버그가 많았는데 지금은 좀 나아진 편입니다.</li>
<li>Broadcom: (32비트 CPU를 쓴다면) 포팅은 가능하겠지만, 무선 칩셋이 작동하지 않을 수 있습니다. 포팅 시도하기 전에 <span class="exturl" data-url="aHR0cHM6Ly93aXJlbGVzcy53aWtpLmtlcm5lbC5vcmcvZW4vdXNlcnMvZHJpdmVycy9icmNtODAyMTE=">드라이버<i class="fa fa-external-link-alt"></i></span>가 해당 칩셋 모델을 지원하는지 미리 확인해보세요.</li>
<li>Realtek: 포팅할 수 없습니다…라고 생각했는데 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL29wZW53cnQvb3BlbndydC9jb21taXQvZGY4ZTZiZTU5YTFmYmNlM2Y4YzY4NzhmZTc0NDBhMTI5YjEyNDVkNg==">이거<i class="fa fa-external-link-alt"></i></span>와 <span class="exturl" data-url="aHR0cHM6Ly9mb3J1bS5vcGVud3J0Lm9yZy90L2FueS1wbGFucy1mb3ItcmVhbHRlay1zb2Mtc3VwcG9ydC8xNTcyNy8yMQ==">이거<i class="fa fa-external-link-alt"></i></span>를 보면 그렇게까지 불가능한 일은 아닐지도 모르겠네요. 현재 snapshot에선 매니지드 스위치에 들어가는 SoC를 지원합니다.</li>
<li>Intel: 포팅할 수 없습니다. 원래 Lantiq란 회사였는데 Intel에 인수됐습니다. 옛날 Lantiq 칩셋은 OpenWrt에서 지원하나 본데 최신 Intel 칩셋은 별다른 소식이 없네요.</li>
<li>Marvell: 포팅도 잘 되고 작동도 잘 하는데 국내 가정용 공유기 시장에선 유난히 존재감이 없습니다. 무선 드라이버인 mwlwifi는 꾸준히 관리는 되고 있지만 메인라인 커널에 들어간 상태는 아닙니다.</li>
</ul>
<p>포팅 가능한 SoC를 쓰고 RAM이 32MB, 플래시가 4MB 이상이면 OpenWrt를 올릴 수 있다고 보면 됩니다.</p>
<p>통신사 공유기는 SoC 지원 이전에 쉘을 얻을 수 있는지부터 걱정해야 할 판이기 때문에 기기 제조사나 통신사가 어딘지가 중요합니다.</p>
<h1 id="ipTIME">ipTIME<a class="header-anchor" href="#ipTIME"></a></h1>
<p>ipTIME 기기는 SoC 제조사별로 이미지 포맷이 좀 많이 다릅니다. 이미지 헤더 생성하는 코드 짜는 것도 일이라…간단할수록 포팅이 쉽겠죠. 11ac 및 유선 공유기에 흔히 쓰이는 MT7621의 경우엔 별다른 제조사 헤더/테일이 없어서 작업이 수월합니다.</p>
<p>현재 아직 단종되지 않은 11ac 리얼텍 모델은 거의 대부분 RTL8197F 계열을 사용하고 있습니다. 특이하게도 RTL8197F는 여타 리얼텍 SoC와 다르게 Lexra가 아닌 진짜배기 MIPS 아키텍처를 사용합니다.</p>
<p>11n 모델도 포팅은 가능하나, 대부분 메모리 사양이 안 좋은 편이기 때문에 만약 OpenWrt를 올린다 하더라도 실사용은 힘들 수도 있습니다.</p>
<p>한때 사측에서 펌웨어 소스코드를 풀었었기 때문에(지금도 공개는 하지만 업데이트는 더 이상 안 해주는 것 같습니다) 포팅 작업시 참고하면 도움이 됩니다.</p>
<p>현재 OpenWrt에서 공식 지원하고 있는 모델은 다음과 같습니다.</p>
<ul>
<li>A604M, A3: MT7628 사용</li>
<li>A104ns, A1004ns: MT7620 사용</li>
<li>A6ns-M, <span class="exturl" data-url="aHR0cHM6Ly9naWdnbGVoZC5jb20vZ2cvYmJzLzYzNzkyODQ=">A8004T<i class="fa fa-external-link-alt"></i></span>: MT7621+MT7615 사용</li>
</ul>
<p>이 외에도 제가 포팅에 성공했던 모델이 몇 개 더 있는데 여러가지 이유로 업스트림에 올리진 않았습니다.</p>
<ul>
<li>N604Black: 32MB RAM</li>
<li>N704BCM, N904ns: WiFi가 안 됨</li>
<li>Extender-N3: 4MB 플래시</li>
<li>A804NS-MU: 복잡한 이미지 헤더</li>
<li>A9004M: NAND BMT 미지원</li>
</ul>
<p>그리고 teslamint님이 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL3Rlc2xhbWludC9vcGVud3J0L2NvbW1pdHMvYTgwMDR0LXhy">A8004T-XR<i class="fa fa-external-link-alt"></i></span>을 포팅한 사례가 있습니다.</p>
<h1 id="그-외-리테일-공유기">그 외 리테일 공유기<a class="header-anchor" href="#그-외-리테일-공유기"></a></h1>
<p>퀄컴을 사용하는 (ipTIME 이외의) 리테일 공유기를 본 적이 없고, 브로드컴은 시도조차 해본 적이 없어서 잘 모릅니다. 아래 내용은 전부 ramips 기종에만 초점을 맞추고 있습니다.</p>
<p>현재 OpenWrt에서 공식 지원하고 있는 모델은 다음과 같습니다.</p>
<ul>
<li>WeVO 11AC NAS Router: <span class="exturl" data-url="aHR0cHM6Ly9ibG9nLnF1ZW5kaS5tb2UvMjAxNi8xMS8xNS9rby13ZXZvLXcyOTE0bnMtdjItJWVkJThiJWIwJWVjJTk2JWI0JWViJThiJWE0JWVjJTlhJWI0JWVhJWIzJWJjLWxlZGUtJWVkJThmJWFjJWVkJThhJWI4Lw==">perillamint님<i class="fa fa-external-link-alt"></i></span>이 공식 지원을 넣었습니다. 비슷한 변종이 여러 개 있습니다.</li>
<li>netis WF2770</li>
<li>netis WF2881: <span class="exturl" data-url="aHR0cHM6Ly9jYWZlLm5hdmVyLmNvbS8wNjJzYW1vLzc4NTU=">luxflow님<i class="fa fa-external-link-alt"></i></span>이 공식 지원을 넣었습니다.<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> 비슷한 변종이 여러 개 있습니다.</li>
<li>ZIO FREEZIO: 보드가 11AC NAS랑 거의 판박이인데, 대신 전원 스위치와 방열판이 추가로 달려있어서 살짝 더 고급이란 느낌은 듭니다.</li>
<li>스토리링크 SAP-G3200U3: <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL29wZW53cnQvb3BlbndydC9jb21taXQvZGNhZTM3MjNmZGRlNGVmNDhlZTEzMzZhYmZiZDJkNTdhMmI4Y2M4NQ==">OpenWrt 메인테이너<i class="fa fa-external-link-alt"></i></span>가 직접 지원을 추가했습니다. 근데 정작 국내엔 거의 알려져있지 않은 것 같네요.</li>
<li>삼성전자 CY-SWR1100: D-Link OEM인 것 같습니다.</li>
</ul>
<p>제가 보기에 WeVO, netis, 스토리링크 공유기는 포팅이 어렵지 않을 것 같습니다. 셋 다 부트로더 쉘에 접근 가능하고, 이미지 검증절차는 uImage 이미지 이름이나 간단한 꼬리 검사 정도뿐이라 커펌을 설치하기 용이해 보입니다.</p>
<p>HUMAX에서 내놓은 공유기는 대부분 인텔이나 리얼텍을 쓰는 걸로 알고 있습니다. 비싸기도 하고 정보도 얻기 어려워서 이쪽은 건드려볼 엄두가 안 나네요.</p>
<p>딴 얘기지만 이지넷 NEXT-7004N 모델은(USB 포트 없는 신 버전은 해당사항 없고 구 버전만) 기가라이트를 지원한다고 제품설명에 적혀있는 유일한 (스위치허브가 아닌) 리테일 공유기인 것으로 보입니다.<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup></p>
<h1 id="통신사-임대-공유기">통신사 임대 공유기<a class="header-anchor" href="#통신사-임대-공유기"></a></h1>
<p>제가 직접 써본 건 KT와 LG U+뿐입니다. SKB는 대부분 리얼텍을 쓰는 것 같아 시도해보지 않았습니다.</p>
<p>리테일 공유기는 퀄컴 쓰는 기종을 찾기가 힘든데 통신사 공유기 중엔 꽤 많은 것 같습니다.</p>
<p>반기가 지원 공유기에는 리얼텍 칩셋이 들어갑니다. RTL8954E나 RTL8696을 쓰나본데 이쪽은 자료찾기가 무척 힘드네요.</p>
<p>같은 통신사 제품 이름을 쓰는데(예를 들어 kt GiGA WiFi Wave 2) 제조사가 다른 모델이 여러 개인 경우가 있기 때문에(예를 들어 머큐리의 KM08-708H, 올래디오의 TI04-708H, 다보링크의 DV01-901H) 정확한 모델명으로 구별하는 게 좋습니다.</p>
<p>대체로 11ac 이후 공유기는 콘솔 접근을 막아놓은 상태입니다.</p>
<h2 id="머큐리">머큐리<a class="header-anchor" href="#머큐리"></a></h2>
<p>머큐리는 주로 리얼텍이나 미디어텍 SoC를 사용하는 것으로 보입니다.</p>
<p>미디어텍 모델을 하나 구해서 열어봤는데 콘솔을 잘 막아놔서 공략이 쉽지가 않았습니다. 11n 공유기는 쉘을 막아놓지 않은 것 같던데 다 리얼텍이라 별로 가치가 없네요.</p>
<h2 id="다보링크">다보링크<a class="header-anchor" href="#다보링크"></a></h2>
<p>다보링크는 주로 리얼텍이나 퀄컴 SoC를 사용하는 것으로 보입니다. 콘솔 접근은 막아놓았지만 보드에 다른 디버그 포트가 있어서 퀄컴 SoC의 경우 어렵지 않게 포팅할 수 있습니다.</p>
<p>어쩌다 들어간 건진 모르겠지만 OpenWrt 지원 기기 목록에 <span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy90b2gvZGF2b2xpbmsvZHYtMjAxYW1y">DV-201AMR<i class="fa fa-external-link-alt"></i></span> 모델이 있습니다. 국내용 모델은 아닌 것 같긴 한데 좀 신기하네요.</p>
<h2 id="올래디오">올래디오<a class="header-anchor" href="#올래디오"></a></h2>
<p>동원티앤아이 -> 티앤아이이 -> 올래디오 순으로 회사명을 바꾸고 지금은 HFR에 인수된 상태입니다.</p>
<p><span class="exturl" data-url="aHR0cHM6Ly9tYW5hdGFpbHMubmV0L2Jsb2cvMjAxOC8wMS9rdC0lRUIlQUMlQjQlRUMlODQlQTAtJUVBJUIzJUI1JUVDJTlDJUEwJUVBJUI4JUIwLSVFQyVCQiVBNCVFQyU4QSVBNCVFRCU4NSU4MC0lRUQlOEUlOEMlRUMlOUIlQTglRUMlOTYlQjQtJUVBJUIwJTlDJUVCJUIwJTlDJUVBJUI4JUIwLw==">manatail님<i class="fa fa-external-link-alt"></i></span>과 <span class="exturl" data-url="aHR0cHM6Ly90Z2Qua3Ivcy9mdW56aW5udS8zNjY4OTM5Ng==">여우는르나르님<i class="fa fa-external-link-alt"></i></span>이 포팅한 공유기 모델인 DW02-412H를 비롯해 DW03-608H과 TI04-708H 모두 퀄컴 SoC를 씁니다.</p>
<p>콘솔 접근을 막아놓긴 했는데 뚫으려고 하면 뚫리긴 합니다. 포팅도 그럭저럭 잘 되고요.</p>
<h2 id="LG전자-한빛전자">LG전자 / 한빛전자<a class="header-anchor" href="#LG전자-한빛전자"></a></h2>
<p>NAPL-5000과 CAPL-6000은 AR7241를 쓰고 보드도 대략 비슷합니다. CAPL이 메모리 용량이 두 배고 USB 포트도 달려있습니다.</p>
<p>사양이 그리 좋지 않고 이미지 포맷이 지저분해서 개인적으로 별로 좋아하는 기기는 아닙니다.</p>
<p>중국 <span class="exturl" data-url="aHR0cHM6Ly93d3cucmlnaHQuY29tLmNuL0ZPUlVNL2ZvcnVtLnBocD9tb2Q9dmlld3RocmVhZCZ0aWQ9MTY5NDY2">포럼<i class="fa fa-external-link-alt"></i></span>이나 <span class="exturl" data-url="aHR0cDovL2Jsb2cuaWNrLmltLyMvcG9zdHMvMg==">블로그<i class="fa fa-external-link-alt"></i></span>를 보면 한때 NAPL이나 CAPL에 UBNT 커펌을 올려 쓴 사람이 꽤 있었던 것 같습니다.</p>
<p>CAPL의 경우 국내에도 <span class="exturl" data-url="aHR0cHM6Ly9rYXN1Z2Fuby50aXN0b3J5LmNvbS8xNTQ=">박윤지님<i class="fa fa-external-link-alt"></i></span>의 포팅 사례가 있습니다.</p>
<h1 id="그-외-통신사-공유기">그 외 통신사 공유기<a class="header-anchor" href="#그-외-통신사-공유기"></a></h1>
<p>지트론이란 데서 만든 WNVR-001이란 공유기가 있습니다. 원랜 CCTV 관리용으로 만들었나본데 사양이 “생각보다” 괜찮습니다.<br>
<span class="exturl" data-url="aHR0cHM6Ly9ibG9nLm5hdmVyLmNvbS96ZXRlbmdpbmU3LzIyMTU0NzMyMzcwOQ==">사용 사례<i class="fa fa-external-link-alt"></i></span>를 보면 지금은 대충 비슷한 모델 펌웨어를 빌려쓰는 것 같은데, 누가 제대로 한번 포팅해보면 좋을 것 같네요.</p>
<p>에그도 일종의 무선전용 공유기라 볼 수 있지 않을까요? 인포마크 에그를 몇 개 살펴봤는데 SoC로 GCT GDM7243를 쓰네요. 메인라인 커널이 지원하지 않는 칩 같은데<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup> 그러면 포팅이 어렵겠죠.</p>
<p>그 외에 유선 포트가 달린 LTE 공유기 같은 것도 있는데, 만약 위의 에그처럼 LTE 모뎀이 통합된 SoC를 쓴다면 포팅이 안 될 것이고, 일반 공유기 SoC에 주변장치로 LTE 모뎀을 달아놓은 거라면 포팅 가능성이 있겠습니다.</p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>링크에 접속할 수 없으면 네이버에서 "WF-2881 커스텀펌웨어 <2017-03-05>"로 검색해보세요. <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>조만간(언젠가?) 리얼텍 특집글을 쓰게되면 거기서 자세한 내용을 다룰 예정입니다. <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>대신 이 칩셋을 USB 모뎀 장치로 사용하는 드라이버는 있네요. <a href="#fnref3" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content>
<categories>
<category>자유시간 프로젝트</category>
</categories>
<tags>
<tag>OpenWrt</tag>
</tags>
</entry>
<entry>
<title>OpenWrt에 새 기기 지원 추가하기</title>
<url>/2020/08/22/openwrt-add-new-device/</url>
<content><![CDATA[<p>※ 2021-09-05: v21.02.0 기준으로 업데이트</p>
<h1 id="들어가기-전에">들어가기 전에<a class="header-anchor" href="#들어가기-전에"></a></h1>
<h2 id="글의-목적">글의 목적<a class="header-anchor" href="#글의-목적"></a></h2>
<p>뭔가 그럴듯한 인트로를 적어보려고 했는데 적당한 표현이 떠오르지 않아 포기하기로 하고, 핵심만 말하자면 국내에 OpenWrt 개발자 공개 커뮤니티라고 할 만한 데가 없어(비공개 네이버 카페는 딥웹이라 보아야 한다고 생각합니다) 관련 정보를 찾기가 쉽지 않은 상황이 아쉬워서, 이런 튜토리얼 비스무리한 거라도 올려 경력있는 신입과 재야에 숨은 고수의 유입을 유도함으로써 저도 편하게 버스타고 가고 싶다는 사적인 소망을 이루고자 이 글을 썼다는 얘기입니다.</p>
<span id="more"></span>
<h2 id="왜-OpenWrt">왜 OpenWrt?<a class="header-anchor" href="#왜-OpenWrt"></a></h2>
<p>OpenWrt는 유무선공유기, NAS, SBC와 같이 자원이 제약된 임베디드 시스템을 위한 리눅스 배포판입니다. 사용자마다 각각의 원하는 점이 있겠지만(무선 성능 개선, 원하는 패키지 설치, 보안 향상 등등) 개인적으로는 잘 정돈된 코드베이스와 개발 환경이라는 데에 큰 점수를 주고 싶습니다. 메인라인에 가까운 최신 버전 커널과 툴체인은 칩셋 제조사 SDK나 그에 의존하는 여타 커펌 프로젝트에선 기대하기 어려운 일이지요. 다른 오픈소스 프로젝트와 비교해봤을 때도 기능성과 복잡도 면에서 Buildroot와 Yocto 사이에 끼어있기에 적당한 타협안이 된다고 생각합니다.</p>
<p>또한 <span class="exturl" data-url="aHR0cHM6Ly9wb3N0bWFya2V0b3Mub3JnLw==">스마트폰<i class="fa fa-external-link-alt"></i></span>, <span class="exturl" data-url="aHR0cHM6Ly93d3cucm9ja2JveC5vcmcv">MP3<i class="fa fa-external-link-alt"></i></span>, <span class="exturl" data-url="aHR0cHM6Ly9xbWsuZm0v">키보드<i class="fa fa-external-link-alt"></i></span> 등과 마찬가지로, 제조사 펌웨어에 발묶여있는 공유기에 오픈소스 커펌을 포팅하는 작업은 코더의 소일거리로도 적당하다고 봅니다.</p>
<h2 id="글의-방향">글의 방향<a class="header-anchor" href="#글의-방향"></a></h2>
<div class="note warning"><p><strong>disclaimer: 케이스를 열거나 커펌을 설치하면 제품 보증이 무효가 되고 자칫하면 기기가 손상될 수 있습니다.</strong><br>
<strong>이 글의 내용을 따라함으로써 (또는 잘못된 방식으로 활용함으로써) 생길 수 있는 결과에 대한 책임은 사용자 스스로에게 있습니다.</strong></p>
</div>
<p>이 글에선 OpenWrt에 새 기기 지원을 추가하는 전반적인 과정(하드웨어 정보를 얻는 것부터 시작해서 업스트림에 패치를 보내는 데까지)을 다루고자 합니다.</p>
<p>이 글은 읽는 사람이 이미 리눅스에 익숙하고 기본적인 하드웨어 지식이 있다는 가정 하에 작성되었습니다.</p>
<p>이 글에서 설명하는 방법과 절차는 최선이 아닐 수 있습니다. 처음에야 일단 따라해보면서 익혀야겠지만, 어느 정도 익숙해지면 여기선 왜 이렇게 했을까, 더 좋은 방법은 없을까, 하고 고민하면서 스스로 개선점을 찾아보길 바랍니다.</p>
<p>예시로 사용할 기기는 제 첫 메인라이닝 모델이면서 하드웨어와 패치가 단순한 ipTIME A604M으로 선택했습니다.<br>
OpenWrt 버전은 2021-09-04 시점에서 최신 안정 버전인 <span class="exturl" data-url="aHR0cHM6Ly9naXQub3BlbndydC5vcmcvYjJhZTQyMzMxNDlk">v21.02.0<i class="fa fa-external-link-alt"></i></span>을 사용하겠습니다. 21.02 이후로 master 브랜치에서 많은 변화가 있었기 때문에 (DSA, nvmem-cells 등) 추후에 기기 지원을 넣으실 분들은 이 글은 참고만 하고 최신 버전에 맞게 작업하셔야 합니다.</p>
<h1 id="사전조사">사전조사<a class="header-anchor" href="#사전조사"></a></h1>
<p>어떤 기기에 OpenWrt를 포팅해보자고 마음을 먹은 다음에 가장 먼저 해야할 일이 뭘까요? 그 기기에 OpenWrt를 올리는 것이 가능할지, 올린 다음에 실사용이 가능할지, 이미 포팅을 시도한 사례가 있는지 등을 먼저 확인하는 과정이 필요합니다. 이미 가지고 있는 기기라면 상관없지만, 덥썩 구매해놓고 나중 가서 올릴 수 없다는 걸 알게 되면 실망이 크잖아요.</p>
<p>일단 A604M의 하드웨어 스펙을 조사해봅시다.</p>
<ul>
<li>SoC: MediaTek MT7628A (580MHz)</li>
<li>RAM: DDR2 64MB</li>
<li>플래시: 8MB</li>
<li>이더넷 포트: 100Mbps WAN x1, 100Mbps LAN x4</li>
<li>WiFi: 2.4GHz 2x2, 5GHz 2x2</li>
</ul>
<p><span class="exturl" data-url="aHR0cDovL2lwdGltZS5jb20vaXB0aW1lLz9wYWdlX2lkPTExJnBmPTMmcGFnZT0mcHQ9MzQ2JnBkPTM=">제품소개<i class="fa fa-external-link-alt"></i></span>에선 WiFi 칩셋으로 뭘 쓰는지까진 안 나오는데, 사실 이 정도만 해도 감지덕지고, 제조사에서 어떤 CPU를 쓰는지조차 알려주지 않는 경우도 흔합니다.</p>
<p>만약 기기의 <span class="exturl" data-url="aHR0cDovL3d3dy5uZXdzdGFwLmNvLmtyL25ld3MvcGhvdG8vMjAxNzEwLzYwMjA0XzkzMjExXzEyMzQuSlBH">내부 사진<i class="fa fa-external-link-alt"></i></span>을 얻을 수 있다면 정보 수집에 큰 도움이 됩니다. 공유기 리뷰어 분들은 겉모습만 찍고 넘기지 말고 분해도 해서 내부 칩이 보이는 사진도 올려주시면 좋겠습니다…</p>
<p>해외/국제 모델의 경우엔 <span class="exturl" data-url="aHR0cDovL3dpa2lkZXZpLndpLWNhdC5ydS8=">WikiDevi<i class="fa fa-external-link-alt"></i></span>와 <span class="exturl" data-url="aHR0cHM6Ly9mY2NpZC5pby8=">fccid.io<i class="fa fa-external-link-alt"></i></span>의 힘을 빌리는 것이 가능합니다. WikiDevi에는 공유기 디바이스 및 칩셋 정보가 모여있고, fccid.io에서는 FCC ID가 있는 제품의 내부 사진을 열람할 수 있습니다.</p>
<p>또한 펌웨어 <span class="exturl" data-url="aHR0cHM6Ly9pcHRpbWUuY29tL2lwdGltZS8/cGFnZV9pZD0xMjYmZGZzaWQ9MyZkZnRpZD0zNzcmdWlkPTE5NzQwJm1vZD1kb2N1bWVudA==">바이너리<i class="fa fa-external-link-alt"></i></span>나 <span class="exturl" data-url="aHR0cDovL2dwbC5pcHRpbWUub3JnL2dwbC9IREQxL0dQTC8=">소스코드<i class="fa fa-external-link-alt"></i></span>도 좋은 정보원이 됩니다.</p>
<p>다시 본론으로 돌아가면, MT7628A는 OpenWrt에서 지원하는 SoC이고 ramips/mt76x8 타겟에 해당합니다.<br>
현재 OpenWrt가 지원하는 플랫폼 중 인기 있는 몇 개를 살펴보자면 다음과 같습니다.</p>
<ul>
<li>ar71xx, ath79: (MIPS 기반) Atheros SoC를 사용합니다. 전자는 mach.c를 사용하고 후자는 DTS를 사용합니다.<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></li>
<li>ipq40xx, ipq806x: (ARM 기반) Qualcomm Atheros SoC를 사용합니다.</li>
<li>bcm47xx, bcm53xx: Broadcom SoC를 사용합니다. 전자는 MIPS 아키텍처고 후자는 ARM 아키텍처입니다.</li>
<li>ramips, mediatek: Ralink/MediaTek SoC를 사용합니다. 전자는 MIPS 아키텍처고 후자는 ARM 아키텍처입니다.</li>
<li>kirkwood, mvebu: Marvell SoC를 사용합니다. 이 계열은 공유기뿐만 아니라 NAS 기기에도 많이 사용됩니다.</li>
</ul>
<p>Lexra 기반의 Realtek SoC는 지원되지 않습니다. 다만 MIPS 기반 RTL838x 계열은 초기 지원이 추가된 상태입니다.</p>
<p>이 중 ramips 타겟은 지원이 잘 되고 있는 상태고, 지원하는 기종도 많은 걸 봤을 때, A604M 포팅에 SoC가 걸림돌이 되진 않을 것으로 보입니다. 또한 OpenWrt의 최소 요구 사양으로 여겨지는 8/64 조건(플래시 8MB 이상, RAM 64MB 이상)도 만족하고 있습니다.</p>
<p>위에 링크를 달아놓은 내부 사진을 잘 살펴보면 보드에 UART로 추측되는 4핀 핀헤더가 달려있는 게 보입니다. 시리얼 콘솔은 디바이스 정보를 얻고 디버깅을 하는 데 필수적이고, 이게 없으면 이후 진행이 매우 골치아파지기 때문에, UART 핀의 존재 여부 정도는 미리 확인해두는 게 좋습니다.</p>
<h1 id="하드웨어-및-펌웨어-조사">하드웨어 및 펌웨어 조사<a class="header-anchor" href="#하드웨어-및-펌웨어-조사"></a></h1>
<p>사전조사에서 OpenWrt를 올릴 수 있을 것 같다는 희망이 보였다면 이제 본격적인 조사 작업에 들어가봅시다.</p>
<p>기기 아랫면의 고무 패킹을 빼고 나사를 풀어줍니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/001-lid.jpg" class="">
<p>제가 분해에 능하지 못해 그러는 걸진 모르겠지만, 남들은 잘만 분해된다는데 나는 아무리 힘을 줘도 뚜껑이 안 열리면 울고 싶어집니다. 노하우를 안다고 해서 분해가 반드시 쉬워지는 건 아니지만, 적어도 걸쇠의 위치라도 안다면 공략이 한결 수월해진다고 생각합니다.</p>
<p>다행히 이 케이스는 별로 걸리적거릴 게 없어서 쉽게쉽게 열립니다.</p>
<p>분해 후 내부 칩의 부품번호를 확인합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/002-internal.jpg" class="">
<ul>
<li>SoC: MediaTek MT7628AN (MIPS 24KEc 580MHz, bgn 2x2)</li>
<li>RAM: ESMT M14D5121632A (DDR2 64MB)</li>
<li>플래시: cFeon QH64-104HIP (SPI NOR 8MB, Eon EN25QH64와 동일한 모델로 보임)</li>
<li>WiFi 5GHz: MediaTek MT7612EN (abgn+ac 2x2)</li>
</ul>
<p>각 부품의 데이터시트도 (찾을 수 있으면) 구해둡니다.</p>
<p>이제 시리얼 포트에 접속해봅니다. 원랜 멀티미터로 전압과 핀아웃을 먼저 확인하는 것이 정석이지만, 프로브 대고 있는 사진을 찍기 귀찮아서 생략하겠습니다. 다행히 A604M은 포트 옆에 핀아웃이 친절하게 적혀있어서 따로 찾아볼 필요가 없겠네요.</p>
<img src="/2020/08/22/openwrt-add-new-device/003-uart.jpg" class="">
<p>잠시 보충설명을 하자면,</p>
<ul>
<li>3~5핀 포트가 있으면 십중팔구 UART이고, 10~20핀 포트가 있으면 JTAG일 가능성이 높습니다.</li>
<li>대부분의 공유기 SoC는 TTL 전압이 3.3V입니다. 하지만 IPQ806X 같은 예외도 있습니다.</li>
<li>GND, RXD, TXD 핀만 연결하면 됩니다. VCC는 (보드에 이미 전원을 넣고 있다면) 불필요할뿐더러 괜한 전압 충돌만 생길 수 있으니 꽂지 마세요.</li>
<li>경험상 Atheros SoC를 사용하는 공유기에서 UART 연결문제가 발생할 때가 많았습니다.(시리얼 어댑터를 연결하고 전원을 넣으면 부팅이 안 된다든가, RX는 되는데 TX가 안 된다든가) 뭔가 잘 안 되면 USB-UART 어댑터를 다른 걸로 바꿔보세요.</li>
</ul>
<p>UART 보율은 어떻게 알아낼까요? 이것도 무작정 시도해보는 방법도 있지만, 보통 SoC별로 많이 쓰는 값이 있기 때문에(일반적으로 115200, ramips는 57600, realtek은 38400) 그것부터 시도해보면 좋습니다. A604M은 57600에 걸렸습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/004-boot-start.png" class="">
<p>전원 넣고서 부팅이 완료될 때까지의 전체 로그를 한 번은 수집해야 합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/005-boot-end.png" class="">
<p>ipTIME 공유기는 부팅이 끝난 다음에 별다른 쉘을 띄워주지 않습니다.</p>
<p>부팅 로그 첫 부분을 보면 부트로더에서 선택지가 뜨는 것을 볼 수 있습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/006-bootloader.png" class="">
<p>WeVO나 netis 공유기에선 부트로더 쉘도 열 수 있는데 ipTIME ramips 기기에선 TFTP 복구모드밖에 쓸 수 없습니다.</p>
<p>이 복구모드는 원래 펌웨어 업데이트에 실패했을 때 부트로더에서 자동으로 진입하는 모드입니다. 딱히 숨겨진 기능이 아니기 때문에 ipTIME 홈페이지에 사용법 <span class="exturl" data-url="aHR0cDovL2lwdGltZS5jb20vaXB0aW1lLz9wYWdlPTImcGFnZV9pZD02NyZ1aWQ9NzM2MCZtb2Q9ZG9jdW1lbnQ=">설명글<i class="fa fa-external-link-alt"></i></span>도 올라와 있습니다.</p>
<p><code>t</code>를 눌러 복구 모드에 들어가면 공유기는 TFTP 서버를 열어줍니다. 컴퓨터에서 고정 IP로 이더넷 연결 후(LAN 포트에 꽂아야 합니다) TFTP 클라이언트를 실행합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/007-tftp-put.png" class="">
<p>일단 기능 테스트를 위해 정펌을 올려봤는데 잘 되네요.</p>
<p>처음 써보는 기기라면 관리자 웹페이지도 둘러보고 LED는 언제 불이 들어오는지도 살펴보고 하면서 기능을 더 탐색해야겠지만, ipTIME 공유기 기능은 다들 아시리라 믿고 넘어가겠습니다.</p>
<h1 id="빌드-및-부팅">빌드 및 부팅<a class="header-anchor" href="#빌드-및-부팅"></a></h1>
<p>이제 OpenWrt 펌웨어를 빌드해봅시다. v21.02.0엔 제가 이미 메인라이닝한 A604M 지원 패치가 들어가 있는데, 이 글에선 없다고 가정하고 진행하겠습니다.</p>
<p>빌드 환경으론 Ubuntu 20.04를 사용하겠습니다. RAM은 4GB, 여유 저장공간은 10GB 이상 있어야 빌드가 수월할 겁니다.</p>
<p>일단 OpenWrt에서 이미 지원하는 mt76x8 디바이스 중 A604M과 사양이 대략 비슷해보이는 <span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy90b2gvaHdkYXRhL2N1ZHkvY3VkeV93cjEwMDBfdjE=">Cudy WR1000<i class="fa fa-external-link-alt"></i></span>의 펌웨어 이미지를 빌드하겠습니다. 이는 디바이스에서 OpenWrt 이미지를 정상적으로 부팅하는 것이 가능한지 테스트해보려는 목적이고, 나중에 제대로 전용 이미지를 만들 겁니다.</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line"><span class="comment">## 패키지 설치 및 저장소 클론</span></span><br><span class="line">sudo apt-get install build-essential libncurses-dev gawk unzip wget python3 git file rsync</span><br><span class="line">git <span class="built_in">clone</span> https://github.com/openwrt/openwrt.git</span><br><span class="line"><span class="built_in">cd</span> openwrt</span><br><span class="line"><span class="comment">## 기존 패치 삭제</span></span><br><span class="line">git switch -c dev-a604m v21.02.0</span><br><span class="line">wget https://mans0n.github.io/2020/08/22/openwrt-add-new-device/v21.02.0-pre-a604m.patch</span><br><span class="line">git am v21.02.0-pre-a604m.patch</span><br><span class="line"></span><br><span class="line"><span class="comment">## 외부 패키지 가져오기, 한 번만 하면 됨</span></span><br><span class="line">./scripts/feeds update -a</span><br><span class="line">./scripts/feeds install -a</span><br><span class="line"><span class="comment">## 빌드 타겟 설정</span></span><br><span class="line">make menuconfig</span><br><span class="line"><span class="comment">## "Target System" -> "MediaTek Ralink MIPS"</span></span><br><span class="line"><span class="comment">## "Subtarget" -> "MT76x8 based boards"</span></span><br><span class="line"><span class="comment">## "Target Profile" -> "Cudy WR1000"</span></span><br><span class="line"><span class="comment">## 빌드 중간에 실패할 때를 대비해 CONFIG_BUILD_LOG도 활성화시켜두면 좋음</span></span><br><span class="line"><span class="comment">## "Advanced configuration options (for developers)" -> "Enable log files during build process"</span></span><br><span class="line">make defconfig</span><br><span class="line"><span class="comment"># ./scripts/diffconfig.sh</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 소스파일 다운로드, 한 번만 하면 됨</span></span><br><span class="line">make download -j3</span><br><span class="line"><span class="comment">## 빌드 시작, (CPU 스레드 수 + 1)개의 프로세스로 병렬처리</span></span><br><span class="line">make -j$((`nproc` + <span class="number">1</span>))</span><br></pre></td></tr></table></figure>
<img src="/2020/08/22/openwrt-add-new-device/008-menuconfig.png" class="">
<p>처음 빌드할 땐 툴체인까지 빌드해야 하기 때문에 시간이 좀 많이 걸립니다. 컴퓨터 성능이 좋다면 30분만에 끝날 수도 있고, 별로라면 한두 시간 걸릴 수도 있습니다.</p>
<div class="note info"><p>참고문서:</p>
<ul>
<li><span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL2d1aWRlLWRldmVsb3Blci9xdWlja3N0YXJ0LWJ1aWxkLWltYWdlcw==">[OpenWrt wiki] Quick Image Building Guide<i class="fa fa-external-link-alt"></i></span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL2d1aWRlLWRldmVsb3Blci9idWlsZC1zeXN0ZW0vdXNlLWJ1aWxkc3lzdGVt">[OpenWrt wiki] Build system usage<i class="fa fa-external-link-alt"></i></span></li>
</ul>
</div>
<p>빌드 후 새로 생기는 디렉토리 몇 개를 살펴보면 다음과 같습니다.</p>
<ul>
<li><code>bin</code>: 빌드 결과물인 펌웨어 이미지와 패키지가 저장되는 장소</li>
<li><code>build_dir</code>: 소스코드가 빌드되는 장소 (만약 저장공간이 부족해진다면 <code>build_dir/toolchain-*</code>부터 삭제하세요)</li>
<li><code>dl</code>: 다운로드 받은 소스 압축 파일이 저장되는 장소</li>
<li><code>staging_dir</code>: 빌드한 툴체인 바이너리나 라이브러리 헤더 등이 저장되는 장소</li>
</ul>
<p>설치에 사용할 이미지는 <code>bin/targets/ramips/mt76x8/</code> 아래에 있습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/009-openwrt-image.png" class="">
<p>참고로 initramfs와 squashfs 이미지의 차이점을 알아보자면,</p>
<ul>
<li>initramfs: 커널과 rootfs가 모두 포함된 이미지입니다. rootfs는 RAM에만 존재하고, 모든 파일 변경사항은 시스템 종료시 사라집니다. U-Boot의 <code>tftpboot</code> 명령어를 쓰면 RAM에 이미지를 바로 올리고 부팅하는 것이 가능합니다. 보통 디버깅용으로 많이 쓰지만, 원한다면 실사용 목적으로 쓸 수도 있습니다.</li>
<li>squashfs: 커널과 읽기전용 rootfs(squashfs)와 읽고쓰기 가능한 추가 파일시스템(jffs2를 overlayfs로 사용)이 담긴 이미지입니다.<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup> 모든 파일 변경사항은 이 overlayfs에 저장되어 플래시에 기록됩니다. 만약 리셋을 한다면 오버레이만 날려버려서 초기상태로 되돌아갑니다.</li>
</ul>
<p>이제부터 하려는 건 정펌 상태에서 커펌을 올릴 수 있는 길을 찾는 것입니다. 가장 확실한 방법은 플래시를 보드에서 떼내서 커펌을 기록하고 다시 보드에 붙이는 방법이지만, 보통은 그렇게까지 하고 싶진 않죠. 통상적으론 다음의 셋 중에 하나를 얻으면 됩니다.</p>
<ul>
<li>루트 권한의 유닉스 쉘</li>
<li>부트로더 쉘</li>
<li>원하는 코드를 실행시킬 수 있는 하드웨어 인터페이스 (JTAG 등)</li>
</ul>
<p>A604M은 이 중에 해당하는 항목이 없지만, 대신 부트로더에서 진입할 수 있는 복구모드가 있었죠.</p>
<p>복구모드도 바보는 아닐 테니 아무 이미지나 막 받아들이진 않을 거고, OpenWrt 이미지를 정펌 포맷에 맞춰줄 필요가 있을 겁니다.</p>
<p>우선 정펌 포맷을 살펴보겠습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/010-binwalk-stock.png" class="">
<p>uImage 헤더가 앞에 달려있고, 커널과 rootfs가 뒤따라오는 구조입니다. <code>hexdump</code>로 살펴봐도 제조사 헤더나 꼬리가 붙어있는 것 같진 않네요.</p>
<p>이걸 아까 빌드한 <code>openwrt-ramips-mt76x8-cudy_wr1000-initramfs-kernel.bin</code> 이미지 포맷과 비교해봅니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/011-binwalk-initramfs.png" class="">
<p>똑같이 uImage 헤더로 시작하고, 뒤에는 커널만 따라옵니다. squashfs가 빠지긴 했지만 구조는 대충 비슷하니 이 정도면 복구모드도 만족해하지 않을까요.</p>
<p>이 initramfs 이미지를 TFTP로 올려보겠습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/012-tftp-fail.png" class="">
<p>이미지를 거부하네요? 정펌 이미지엔 <code>a604m</code>이라 적혀있는 부분이 initramfs 이미지엔 <code>MIPS OpenWrt Linux-5.4.143</code>이라 적혀있어서 안 된다는 것 같습니다. 아까 <code>binwalk</code> 결과에서 uImage 헤더의 이미지 이름란에 이런 문자열이 들어가 있었죠.</p>
<p>다행히 이건 이미지 Makefile에 한 줄만 추가해주면 해결됩니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/013-uimage-name.png" class="">
<p>다시 이미지를 빌드하고 TFTP로 올리면 이번엔 이미지를 정상적으로 접수합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/014-tftp-success.png" class="">
<p>부팅이 끝나고 쉘이 뜨면 성공한 겁니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/017-boot-success.png" class="">
<p>Q: 근데 아직 플래시 덤프도 안 했는데 너무 무작정 설치해버린 거 아닌가요?<br>
A: 네 맞습니다… 경험상 ipTIME ramips 기기에서 부트로더 복구모드를 믿어도 괜찮고, 덤프는 나중에 남은 부분만 해도 충분하다는 걸 알기 때문에 이렇게 간 거고, 다른 디바이스 작업할 땐 꼭 덤프부터 하세요.<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup></p>
<h1 id="기능-살리기">기능 살리기<a class="header-anchor" href="#기능-살리기"></a></h1>
<p>OpenWrt 부팅에 성공했으니, 이제 본격적으로 디바이스 지원 패치를 작성해봅시다.</p>
<p>일단 A604M 이미지를 만드는 것부터 시작하겠습니다. WR1000 지원 패치를 복사해 A604M으로 이름만 바꿔줍니다. <code>wr1000</code>로 검색하면 금방 찾을 수 있습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/018-grep-wr1000.png" class="">
<p>대충 이 정도? 별로 안 많죠? dts는 파일을 새로 만들어야 합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/019-menuconfig-a604m.png" class="">
<p>이 다음에 <code>make menuconfig</code>를 다시 하면 모델 목록에 A604M이 뜹니다. 새로 빌드한 <code>openwrt-ramips-mt76x8-iptime_a604m-initramfs-kernel.bin</code> 이미지로 재설치하면 이전처럼 잘 부팅되어야 합니다.</p>
<p>다음으로 넘어가기 전에 잠깐 DTS가 무엇인지에 대해 짧게 설명하겠습니다.</p>
<p>예전엔 (그리고 지금도 일부는) 각 기기 모델마다 존재하는 <code>mach-*.c</code> 또는 <code>board-*.c</code>에서 주변장치 초기화 및 설정 작업을 진행했지만, 현재는 이 목적을 위해 DTS(Device Tree Source)라는 별개 형식의 파일을 사용하는 추세입니다. dtc라는 별도의 컴파일러를 써서 DTS 소스파일을 DTB 바이너리로 만들고, 이걸 커널 이미지 옆에 덧붙이거나 저장장치 어딘가에 저장해놨다가 부팅 시 불러와서 사용합니다. DT는 실행 코드가 아니라 단순히 하드웨어를 기술하는 역할만 하고, 드라이버는 DTB를 읽어들여 기기에 어떤 장치가 달려있고 각각을 어떻게 사용해야 하는지 파악합니다.</p>
<p>참고로 모든 기기가 디바이스 트리를 쓰는 건 아니고, 이외에도 여러 하드웨어 정보 관리 방법이 있습니다. 브로드컴 공유기는 nvram을 사용하기도 하고, x86 컴퓨터에선 ACPI(특히 DSDT)를 사용합니다.</p>
<p>ramips는 아직 커널 메인라이닝이 덜 됐기 때문에 아직도 많은 부분이 OpenWrt 다운스트림 패치로 남아있고, dts도 커널 소스트리에 들어간 걸 쓰지 않고 <code>target/linux/ramips/dts/</code>에 있는 로컬 파일을 사용합니다. 내용을 보면 SoC의 전반적인 기능을 dtsi 파일에서 정의하고, 이걸 디바이스 dts에서 불러와 필요한 기능만 활성화시켜 사용하는 구조로 되어있습니다.</p>
<div class="note info"><p>참고문서:</p>
<ul>
<li><span class="exturl" data-url="aHR0cHM6Ly9lbGludXgub3JnL2ltYWdlcy9mL2Y5L1BldGF6em9uaS1kZXZpY2UtdHJlZS1kdW1taWVzXzAucGRm">Device Tree for Dummies<i class="fa fa-external-link-alt"></i></span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly9qdW5nLW1heC5naXRodWIuaW8vMjAxOS8xMC8yMi9EZXZpY2VfVHJlZV8lRUIlQUMlQjglRUIlQjIlOTUv">Device Tree 문법<i class="fa fa-external-link-alt"></i></span></li>
</ul>
</div>
<p>이제부터 할 일은 A604M의 기능을 하나씩 살려나가는 것입니다. 확인해야 할 항목을 꼽아보자면 이더넷, 플래시, WiFi, LED, 버튼 정도가 되겠네요.</p>
<p>뭘 어떻게 해야 하는 건지 막막할 땐 다른 디바이스 지원 패치에선 어떻게 했는지 소스코드나 커밋 로그를 찾아보세요. DT 속성의 의미나 사용방법이 궁금할 땐 커널 <code>Documentation/devicetree/bindings/</code> 경로 아래 있는 문서를 읽어보면 도움이 됩니다.</p>
<div class="note info"><p>참고문서:</p>
<ul>
<li><span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL2d1aWRlLWRldmVsb3Blci9hZGRpbmdfbmV3X2RldmljZQ==">[OpenWrt wiki] Adding a new device<i class="fa fa-external-link-alt"></i></span></li>
</ul>
</div>
<h2 id="이더넷">이더넷<a class="header-anchor" href="#이더넷"></a></h2>
<p>일단 이더넷이 돼야 이후 작업이 편해집니다. 이더넷 설정은 dts와 <code>02_network</code>에 담겨있습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/020-dts-esw.png" class="">
<p><code>&esw</code> 노드는 그냥 날려버립니다. <code>mediatek,portmap</code> 속성은 스위치 LAN/WAN 설정하는 역할인데, 이건 잠시 후에 <code>02_network</code>에서 할 거라 여기선 빼도 됩니다. <code>&ethernet</code> 노드는 지금은 그대로 둡니다.</p>
<p>LAN/WAN 설정을 하기 위해선 각 포트가 MT7628A에 내장된 이더넷 스위치의 몇 번 포트에 해당하는지를 알아야 합니다. 이건 <code>swconfig</code>를 쓰면 쉽게 알아낼 수 있습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/021-swconfig.png" class="">
<p>처음에 외부 포트에 아무 선도 꽂지 않으면 6번 포트만 연결된 것으로 나옵니다. 6번 포트는 스위치와 CPU를 연결하는 내부포트이겠지요. 그리고 WAN 포트에 선을 꽂으니 0번 포트가 연결된 것으로 뜹니다.</p>
<p>이런 식으로 각 외부포트와 스위치 포트번호를 짝지으면 이렇게 나옵니다.</p>
<ul>
<li>0번 포트 - WAN</li>
<li>1번 포트 - LAN 4</li>
<li>2번 포트 - LAN 3</li>
<li>3번 포트 - LAN 2</li>
<li>4번 포트 - LAN 1</li>
<li>6번 포트 - CPU</li>
</ul>
<p>이걸 <code>02_network</code>에 적을 겁니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/022-setup-interfaces.png" class="">
<p><code>2:lan:3</code>의 의미는 스위치 2번 포트가 LAN 3 포트와 연결되어 있다는 뜻입니다.</p>
<p>이제 이더넷 LAN/WAN이 모두 잘 될 겁니다. 컴퓨터와 외부 인터넷 선을 꽂아서 확인해보세요.</p>
<img src="/2020/08/22/openwrt-add-new-device/023-ethernet-test.png" class="">
<h2 id="플래시">플래시<a class="header-anchor" href="#플래시"></a></h2>
<p>A604M은 저장장치로 SPI NOR 플래시를 사용합니다. 리눅스에서는 이러한 FTL이 없는 플래시 칩을 MTD 장치로 나타냅니다. MTD 저장공간을 파티션으로 분할하려면 하드 디스크처럼 파티션 테이블을 쓰는 게 아니라, 파티션 정보를 커널 또는 dts에 직접 적어줘야 합니다.</p>
<p>정펌 부팅 로그를 보면 mtd 파티션을 어떻게 나눠놨는지가 뜹니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/024-stock-partition.png" class="">
<p>대충 정리해보면 이렇습니다.</p>
<table>
<thead>
<tr>
<th>파티션 시작 위치</th>
<th>파티션 크기</th>
<th>파티션 이름</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x000000</td>
<td>0x020000</td>
<td>bootloader</td>
</tr>
<tr>
<td>0x020000</td>
<td>0x010000</td>
<td>config</td>
</tr>
<tr>
<td>0x030000</td>
<td>0x010000</td>
<td>factory</td>
</tr>
<tr>
<td>0x040000</td>
<td>0x7c0000</td>
<td>firmware</td>
</tr>
</tbody>
</table>
<p>bootloader 파티션엔 U-Boot 부트로더가 있을 거고, firmware 파티션엔 정펌 이미지가 들어가 있겠죠.<br>
factory 파티션은 보통 무선 칩셋이 사용하는 캘리브레이션 데이터와 MAC 주소를 담는 장소고, config 파티션엔 보통 부트로더 환경변수나 기기 설정값(WiFi SSID와 비번 등)이 담겨있습니다.</p>
<p>이걸 dts에 옮겨 적습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/025-dts-partition.png" class="">
<ul>
<li>"firmware"는 OpenWrt에서 특별한 파티션 이름입니다. 커널은 이 이름의 파티션을 살펴보고 kernel, rootfs, rootfs_data 파티션으로 분할합니다.</li>
<li><code>compatible = "denx,uimage"</code>는 펌웨어 이미지가 uImage 포맷임을 알리는 속성입니다.</li>
<li>firmware 파티션 이외엔 손대서 좋을 게 없으니 읽기전용으로 강제합니다. 만약 읽기전용 파티션을 수정해야 할 일이 생긴다면 <code>kmod-mtd-rw</code>를 쓰세요.</li>
<li><code>spi-max-frequency</code>는 플래시 I/O 속도를 결정합니다. 이 값이 너무 작으면 읽기쓰기 속도가 느리고, 너무 크면 CPU가 플래시를 인식하지 못합니다. 이 값을 제대로 정하는 과정은 좀 복잡한데, 일단 <span class="exturl" data-url="aHR0cDovL3d3dy5iZHRpYy5jb20vZGF0YXNoZWV0L0VPTi9FTjI1UUg2NC5wZGY=">플래시 데이터시트<i class="fa fa-external-link-alt"></i></span>에 따르면 50MHz 이하로 두는 게 안전할 것 같습니다.<img src="/2020/08/22/openwrt-add-new-device/026-flash-freq.png" class="">
</li>
</ul>
<p>아직 플래시 덤프를 못 했죠? 이제 할 수 있습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/027-flash-dump.png" class="">
<p>개인적으론 플래시 전체 크기의 파티션을 따로 만들어서 덤프하는 방법을 선호합니다.</p>
<p>NOR는 대체로 살리기도 쉽고 덤프하기도 쉬운데, NAND는 ECC나 BBT 등 신경써줘야 할 게 많아서 더 복잡합니다.</p>
<div class="note info"><p>참고문서:</p>
<ul>
<li><span class="exturl" data-url="aHR0cDovL3d3dy5saW51eC1tdGQuaW5mcmFkZWFkLm9yZy9mYXEvZ2VuZXJhbC5odG1s">Linux MTD FAQ<i class="fa fa-external-link-alt"></i></span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL3RlY2hyZWYvZmxhc2gubGF5b3V0">[OpenWrt wiki] The OpenWrt Flash Layout<i class="fa fa-external-link-alt"></i></span></li>
</ul>
</div>
<h2 id="WiFi">WiFi<a class="header-anchor" href="#WiFi"></a></h2>
<p>보드에 WiFi 칩셋이 두 개 있었죠. MT7628A는 2.4GHz 대역을 담당하고, PCIe로 연결된 MT7612E는 5GHz 대역을 담당합니다. 각각은 factory 파티션에 저장된 캘값을 필요로 하고, dts에는 이 캘값의 위치를 적어주어야 합니다.</p>
<p>factory 파티션 내용을 쭉 훓어보면 알겠지만, 대부분의 공간은 텅 비어있고 0x0 부분과 0x8000 부분에 약간의 데이터가 저장되어 있습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/028-factory-entropy.png" class="">
<p>이 중에 어떤 게 누구 건지 어떻게 알 수 있을까요? 가장 간단한 방법은 둘 다 시도해보는 겁니다. 캘값엔 칩셋 정보도 들어가있기 때문에 잘못 넣으면 못 받아먹고 토해냅니다.<sup class="footnote-ref"><a href="#fn4" id="fnref4">[4]</a></sup></p>
<p>또 다른 방법은 MAC 주소를 비교해보는 겁니다. 보통 WiFi 칩셋마다 서로 다른 MAC 주소를 할당하기 때문에, 정펌 상태에서 어떤 주소를 쓰는지 확인하고 캘값에 적힌 주소와 비교해보면 되겠습니다. WiFi AP의 MAC 주소는 관리자 웹페이지에서 확인할 수도 있고, WiFi 스캔 앱이나 <code>iw</code> 명령어로 확인할 수도 있습니다.</p>
<p>제 기기의 MAC 주소는 이렇습니다.</p>
<ul>
<li>2.4GHz: 88:36:6c:xx:xx:<strong>dc</strong></li>
<li>5GHz: 88:36:6c:xx:xx:<strong>de</strong></li>
</ul>
<p>보통 마지막 바이트만 살짝 다르게 나옵니다. 이 주소를 factory 파티션에서 검색해봅니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/029-flash-wifi-mac.png" class="">
<p>0x0이 2.4GHz, 0x8000이 5GHz네요. 이걸 dts에 적어줍니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/030-dts-wifi.png" class="">
<ul>
<li><code>&wmac</code>은 MT7628A의 내장 WiFi 모듈입니다. <code>0x0</code>은 SoC dtsi에 이미 들어가있으니 다시 안 써줘도 됩니다.</li>
<li>MT7628A는 PCIe 포트가 하나밖에 없어서 별로 상관없지만, 포트가 여러 개인 기기에서 작업할 땐 <code>lspci -nn</code>으로 어떤 게 어디에 물려있는지 확인해야 합니다.</li>
<li><code>ieee80211-freq-limit</code>는 WiFi 칩셋이 사용할 주파수 대역을 제한하기 위해 사용합니다. 원래 MT7612E는 2.4GHz와 5GHz를 둘 다 지원하는데, A604M에선 5GHz 안테나 선만 연결해서 사용하고 있습니다. 하지만 커널은 그걸 모르니 수동으로 알려줘야 합니다.</li>
<li><code>wifi@0,0</code> 안에 <code>led</code> 노드는 MT7612E의 LED 핀을 위한 설정인데, 뒤에서 보겠지만 A604M에선 사용되지 않으므로 지웁니다.</li>
</ul>
<p>WiFi 커널 모듈도 추가해줘야 하는데, <code>kmod-mt7603</code>과 <code>kmod-mt76x2</code>가 이미 이미지에 포함되어 있어서 더 건들 게 없습니다.</p>
<p>WiFi 작동확인을 하려면 <code>/etc/config/wireless</code>에서 장치를 켜면 됩니다. 자세한 방법은 <span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL2d1aWRlLXVzZXIvbmV0d29yay93aWZpL2Jhc2lj">위키 문서<i class="fa fa-external-link-alt"></i></span>를 참조하세요.</p>
<img src="/2020/08/22/openwrt-add-new-device/031-iwinfo.png" class="">
<h2 id="이더넷-MAC-주소">이더넷 MAC 주소<a class="header-anchor" href="#이더넷-MAC-주소"></a></h2>
<p>이더넷 MAC 주소도 정펌과 같게 해주는 게 좋습니다. 이것도 관리자 웹페이지에서 확인하거나 <code>arp-scan</code> 명령어로 직접 확인할 수 있습니다.</p>
<p>또는 정펌 부팅 로그에서 읽어올 수도 있고요.</p>
<img src="/2020/08/22/openwrt-add-new-device/032-stock-eth-mac.png" class="">
<p>이 MAC 주소는 이상하게 부트로더 파티션에 있네요.</p>
<img src="/2020/08/22/openwrt-add-new-device/033-flash-eth-mac.png" class="">
<p>LAN 주소는 dts에, WAN 주소는 <code>02_network</code>에 적어줍니다. 둘 다 <code>02_network</code>에 넣어도 되긴 하지만, 커널한테도 귀띔해줘서 나쁠 거 없으니까요.</p>
<img src="/2020/08/22/openwrt-add-new-device/034-dts-ethernet.png" class="">
<img src="/2020/08/22/openwrt-add-new-device/035-setup-macs.png" class="">
<p>이제 MAC 주소가 다 맞게 되었네요.</p>
<img src="/2020/08/22/openwrt-add-new-device/036-mac-addr.png" class="">
<ul>
<li>만약 플래시에 정확하게 일치하는 MAC 주소가 없으면 비슷한 주소에다 차이값을 더해서 쓸 수 있습니다.</li>
<li>기기 어딘가에 대표 MAC 주소가 적혀 있으면 <code>label-mac</code>에 넣을 수 있지만, ipTIME은 더 이상 보드에 MAC 주소 스티커를 붙이지 않는 모양입니다.</li>
</ul>
<div class="note info"><p>참고문서:</p>
<ul>
<li><span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL2d1aWRlLWRldmVsb3Blci9tYWMuYWRkcmVzcw==">[OpenWrt wiki] Device Support: MAC address setup<i class="fa fa-external-link-alt"></i></span></li>
</ul>
</div>
<h2 id="USB">USB<a class="header-anchor" href="#USB"></a></h2>
<p>A604M엔 외부 USB 포트가 없습니다. 보드에 USB 포트 흔적이 남아있긴 한데, 굳이 납땜해서 달고 싶은 마음은 안 드네요.</p>
<p>왠진 모르겠지만 SoC dtsi에서 USB를 기본적으로 활성화해둔 상태이므로 dts에서 비활성화해둡니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/037-dts-usb.png" class="">
<ul>
<li>ohci는 USB 1.1, ehci는 USB 2.0, xhci는 USB 3.0에 해당합니다.</li>
<li>USB 포트가 여러 개인 경우 <code>lsusb -t</code> 명령어를 쓰면 어떤 게 어느 건지 구별할 때 도움이 됩니다.</li>
<li>USB 포트의 전원핀(VBUS)을 GPIO로 제어하는 경우도 있습니다. 전원 LED가 달려있는 USB 장치가 있으면 드라이버 문제인지 VBUS 문제인지 판별할 수 있겠죠.</li>
</ul>
<h2 id="LED와-버튼">LED와 버튼<a class="header-anchor" href="#LED와-버튼"></a></h2>
<p>A604M에 달린 LED와 버튼 목록은 다음과 같습니다.</p>
<ul>
<li>LED: 전원, CPU, WiFi 2.4G, WiFi 5G, LAN 1~4, WAN</li>
<li>버튼: WPS, 리셋</li>
</ul>
<p>LED 중에서 소프트웨어로 제어해야 하는 건 CPU와 WiFi 정도네요. 전원 LED는 VCC에 직결되어 있고, LAN/WAN LED는 스위치에서 자동제어 해주는데 굳이 건들 필요 없겠죠.</p>
<p>보통 이런 LED는 SoC의 GPIO 핀에 연결되어 있습니다. 어떤 LED가 몇 번 핀에 달려있는지 확인하기 위해선 GPIO 핀을 차례로 올렸다 내렸다 하면서 반응하는 LED를 찾는게 일반적인 방법이지만, 지금 보니 커널 버전이 5.4로 올라가면서 gpio 드라이버가 바뀌고 핀 순서가 뒤죽박죽 되어버렸네요. 에휴… 그냥 바로 지름길로 가겠습니다.</p>
<p><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2lwdGltZS1ncGwvdXNlcmFwcHNfYTYwNG0vYmxvYi9tYXN0ZXIvZnMvbXQ3NjIxL2Nsb25lcy9hNjA0bS9zaS9odw==">정펌 소스<i class="fa fa-external-link-alt"></i></span>를 보면 LED/버튼의 핀 번호가 나와있습니다.<sup class="footnote-ref"><a href="#fn5" id="fnref5">[5]</a></sup> 예를 들어 WiFi 5G LED는 5번 핀이라고 하네요.</p>
<ul>
<li>CPU LED: GPIO #11</li>
<li>WiFi 2.4G LED: GPIO #46</li>
<li>WiFi 5G LED: GPIO #5</li>
<li>리셋 버튼: GPIO #38</li>
<li>WPS 버튼: GPIO #45</li>
</ul>
<p><span class="exturl" data-url="aHR0cDovL3Zvbmdlci5jbi91cGxvYWQvTVQ3NjI4X0Z1bGwucGRm">MT7628 데이터시트<i class="fa fa-external-link-alt"></i></span>를 보면 각 GPIO 핀이 SoC에서 어떤 다른 역할을 할 수 있는지 적혀있습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/038-pin-table.png" class="">
<p>그러니까 GPIO 5번 핀은 I2C SDA 핀으로도 쓰일 수 있다는 겁니다. 이 핀을 I2C가 아니라 GPIO로 쓰고 싶다면 dts pinctrl 노드에 이를 명시해주어야 합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/039-dts-pinctrl.png" class="">
<p>콘솔에서 GPIO 제어 한번 안 해보고 이대로 지나가버리는 건 좀 섭섭하니 핀 테스트도 해봅시다.</p>
<img src="/2020/08/22/openwrt-add-new-device/040-sysfs-gpio.png" class="">
<p>5번 핀은 리눅스에서 gpio485에 해당합니다. 이미 export된 gpio는 아직 삭제 안한 WR1000의 LED와 버튼입니다.<br>
<code>value</code>에 0을 넣으면 LED가 켜지고, 1을 넣으면 LED가 꺼질 겁니다. LED가 켜질 때 또는 버튼이 눌릴 때(active) GPIO가 1(high)이면 active high, GPIO가 0(low)이면 active low라고 합니다.</p>
<p>이 정보를 바탕으로 dts 노드를 작성합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/041-dts-led-key.png" class="">
<img src="/2020/08/22/openwrt-add-new-device/042-dts-status-led.png" class="">
<ul>
<li><code>linux,code</code>는 해당 버튼이 눌릴 때 입력될 신호를 지정합니다.</li>
<li><code>linux,default-trigger</code>는 해당 LED가 사용할 트리거를 지정합니다. <code>phy0tpt</code>는 WiFi phy0 장치에 트래픽이 발생할 때 깜박이는 트리거입니다.</li>
<li>dts에서 지정하지 못하는 트리거는 <code>01_leds</code>에서 처리하는데, A604M은 dts에서 모든 LED 설정을 마쳤으므로 <code>01_leds</code> 설정은 빼버립니다.</li>
<li><code>led-boot</code> alias는 OpenWrt가 부팅하는 동안 깜박일 상태 LED를 지정합니다.</li>
<li>SoC GPIO가 아닌 외부 WiFi 칩셋이나 GPIO expander 등에 LED가 연결된 경우도 있습니다. 이런 LED를 찾아서 제어하려면 먼저 해당 칩셋 드라이버를 켜고 dts에서 추가 작업을 해야 합니다.</li>
</ul>
<p>이제 LED와 버튼이 모두 작동할 것입니다. 참고로 OpenWrt에서는 버튼이 눌리면 <code>/etc/rc.button/</code>에 있는 스크립트가 실행됩니다.</p>
<div class="note info"><p>참고문서:</p>
<ul>
<li><span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL3RlY2hyZWYvaGFyZHdhcmUvcG9ydC5ncGlv">[OpenWrt wiki] GPIO<i class="fa fa-external-link-alt"></i></span></li>
</ul>
</div>
<h2 id="Failsafe">Failsafe<a class="header-anchor" href="#Failsafe"></a></h2>
<p>OpenWrt를 쓰다가 뭔가 설정을 잘못해서 더 이상 원격 접속이 안 되는 상황이 생길 수 있습니다. 이럴 때를 대비해 OpenWrt에도 안전 모드 같은 게 있는데, 이게 바로 failsafe 모드입니다. 부팅 중에 상태 LED가 빠르게 깜박일 때 콘솔에서 <code>f</code>를 누르거나 보드에 달린 아무 버튼을 누르면 failsafe 모드로 진입합니다. 공유기는 192.168.1.1 고정 IP 상태가 되고, 외부에서 고정 IP로 유선 연결해서 ssh 접속을 할 수 있게 됩니다.</p>
<p>이걸 왜 여기서 다루냐면, 디바이스 지원 패치를 작성하면서 failsafe 모드가 정상 작동하는지도 확인할 필요가 있기 때문입니다. 갑자기 큰일이 생겨서 failsafe 모드에 의존할 일이 생겼는데, 이더넷 설정에 문제가 있어서 ssh 접속이 안 되면 눈물이 나겠죠. 대부분의 경우엔 별다른 추가 설정 필요없이 잘 될 겁니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/043-failsafe-mode.png" class="">
<h2 id="부트로더">부트로더<a class="header-anchor" href="#부트로더"></a></h2>
<p>정펌 부트로더에는 이런저런 기능적 제약이 걸려있는 경우가 많기 때문에 U-Boot 부트로더를 새로 빌드해 갈아치우는 경우도 꽤 있습니다. 이 경우 U-Boot 지원 패치도 따로 만들어서 넣어야 합니다.</p>
<p>하지만 A604M의 경우엔 굳이 바꾸지 않아도 잘 돌아가고, ramips 타겟에선 부트로더는 그대로 두는 경우가 많아서 여기서도 따로 건들지 않겠습니다.</p>
<h1 id="설치법">설치법<a class="header-anchor" href="#설치법"></a></h1>
<p>이제 기기의 웬만한 기능은 다 살려놨습니다. 마지막으로 설치 이미지를 만들어봅시다.</p>
<p>OpenWrt에선 squashfs 설치 이미지를 크게 두 가지로 분류합니다.</p>
<ul>
<li>factory: 정펌에서 OpenWrt를 설치할 때 사용하는 이미지입니다. 제조사의 펌웨어 검증 절차를 통과하기 위해 이상한 게 덕지덕지 붙어있는 경우가 많습니다.</li>
<li>sysupgrade: 이미 OpenWrt가 설치된 기기에서 다시 OpenWrt를 설치할 때(보통 새 버전으로 업그레이드 할 때) 사용하는 이미지입니다.</li>
</ul>
<p>factory 이미지가 반드시 따로 존재할 필요는 없습니다. 만약 정펌에서 sysupgrade 이미지를 바로 설치하는 게 가능하면 sysupgrade가 factory 역할도 하게 되는 겁니다.</p>
<blockquote>
<p>으… 매번 "이미지"를 반복하는 것도 슬슬 귀찮아지니 앞으로 initramfs, factory, sysupgrade 이미지를 각각 I펌, F펌, S펌으로 줄여서 부르겠습니다.</p>
</blockquote>
<p>일단 S펌부터 살펴보겠습니다. 따로 이미지 생성방법을 지정하지 않으면 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL29wZW53cnQvb3BlbndydC9ibG9iL2IyYWU0MjMzMTQ5ZGZkNzhmMmFjMDBiYjUzMjc2OTViY2FjZGMyNTUvdGFyZ2V0L2xpbnV4L3JhbWlwcy9pbWFnZS9NYWtlZmlsZSNMMTY5">기본 레시피<i class="fa fa-external-link-alt"></i></span>에 따라 S펌이 빌드됩니다.</p>
<p>빌드 이미지 디렉토리에 있는 S펌 포맷을 확인합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/044-binwalk-sysupgrade.png" class="">
<p>uImage 헤더로 시작하고, 커널과 rootfs가 뒤따라오는 건 정펌과 매우 유사해 보입니다. 오…? 그러면 복구모드에서 S펌을 받아들일지도 모르겠네요.</p>
<img src="/2020/08/22/openwrt-add-new-device/045-boot-sysupgrade.png" class="">
<p>해보니 잘 됩니다. S펌 첫 부팅은 jffs2 초기화 때문에 시간이 더 걸립니다.</p>
<p>OpenWrt를 재설치할 땐 <code>sysupgrade</code> 명령어를 쓰고, 모델별 재설치 절차는 <code>platform.sh</code>에서 지정합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/046-platform-do-upgrade.png" class="">
<p>ramips 타겟의 기본 재설치 절차는 <code>default_do_upgrade</code>인데, 이건 NOR 플래시의 firmware 파티션에 이미지를 설치하는 일반적인 방법입니다.</p>
<p>OpenWrt를 재설치하면 기존에 설치해둔 패키지 등은 사라지지만, <code>/etc/config/</code>에 있는 설정값은 보존됩니다. 한번 테스트 해보겠습니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/047-sysupgrade-start.png" class="">
<p>hostname을 "a604m"으로 바꾸고 재설치를 했으니 다음에 부팅하면 hostname이 a604m으로 떠야합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/048-sysupgrade-success.png" class="">
<p>그리고 실제로 그렇게 됐네요. 이로써 재설치 기능도 검증이 된 셈입니다.</p>
<p>개인이 혼자 사용할 거라면 이걸로 포팅이 끝났다고 볼 수 있지만, 만약 지원 패치를 업스트림에 머지시킬 생각이라면 보다 손쉬운 설치법을 찾는 게 좋을 겁니다. 모든 사람이 시리얼 어댑터를 가지고 있는 건 아니니까요.</p>
<p>가장 좋은 방법은 정펌 관리자 웹페이지의 펌업 메뉴를 이용하는 것입니다. 이것만큼 쉬운 방법도 없겠죠.</p>
<img src="/2020/08/22/openwrt-add-new-device/049-stock-web-sysupgrade.png" class="">
<p>S펌을 업로드하고 플래싱하고 OpenWrt로 부팅하는 데까진 잘 되는데, 중간에 커널 패닉이 나면서 부팅에 실패합니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/050-no-rootfs.png" class="">
<p>요지는 rootfs를 못 찾겠다는 얘깁니다. 대체 왜? <code>tftpboot</code>를 쓸 수 있다면 플래시 덤프라도 해보겠지만, 방법이 없으니 펌업 로그라도 읽어봐야죠.</p>
<img src="/2020/08/22/openwrt-add-new-device/051-stock-mtd-write.png" class="">
<p>정펌에서 플래싱을 할 때 2000536 바이트만큼 기록하겠다고 하네요. 1.9MB는 너무 적은데요. 이 값은 어디서 온 걸까요?</p>
<p>아까 S펌 <code>binwalk</code> 결과에서 uImage 헤더의 이미지 크기란에 2000472 바이트라고 적혀있었습니다. 2000472는 커널만 포함하는 크기고, rootfs는 딱 2000536(= 2000472 + 64) 바이트 지점에서 시작합니다. 이 말인즉슨, 정펌은 헤더의 이미지 크기란을 기준으로 플래싱을 하고, S펌의 uImage는 딱 커널까지만 포함하기 때문에, 그 이후 부분이 플래싱이 되지 않아 커널이 rootfs를 못 찾는 겁니다.</p>
<p>두 이미지의 포맷 차이를 그림으로 대충 그려보면 이렇습니다.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"># 정펌</span><br><span class="line"> ┌─────uImage─────┐ </span><br><span class="line">┌────┬────┬─────┐</span><br><span class="line">│ header │ kernel │ squashfs │</span><br><span class="line">└────┴────┴─────┘</span><br><span class="line"></span><br><span class="line"># S펌</span><br><span class="line"> ┌──uImage──┐ </span><br><span class="line">┌────┬────┬─────┬───────┬─────┐</span><br><span class="line">│ header │ kernel │ squashfs │ jffs2 marker │ metadata │</span><br><span class="line">└────┴────┴─────┴───────┴─────┘</span><br></pre></td></tr></table></figure>
<p>만약 uImage가 커널 이후 범위도 포함하게 한다면 어떨까요? 제가 알아본 바로는, OpenWrt의 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL29wZW53cnQvb3BlbndydC9ibG9iL2IyYWU0MjMzMTQ5ZGZkNzhmMmFjMDBiYjUzMjc2OTViY2FjZGMyNTUvdGFyZ2V0L2xpbnV4L2dlbmVyaWMvZmlsZXMvZHJpdmVycy9tdGQvbXRkc3BsaXQvbXRkc3BsaXRfdWltYWdlLmMjTDIwMA==">mtdsplit 코드<i class="fa fa-external-link-alt"></i></span>는 uImage가 커널만 포함하는 걸 전제로 짜여있기 때문에, 헤더를 수정하면 아마 커널이 rootfs를 못 찾을 겁니다.</p>
<p>그러면 정펌 관리자 웹페이지를 통해선 OpenWrt 설치가 불가능한 걸까요? 다행히도 방법이 남아있습니다. I펌은 이미 정펌 포맷에 들어맞기 때문에 웹페이지에서도 펌업이 잘 됩니다. 그럼 I펌을 F펌으로 쓰면 되겠죠. 다만 위에서 말했듯 I펌은 파일 변경사항이 저장이 안 되기 때문에 다시 S펌으로 재설치할 필요는 있을 겁니다.</p>
<p>여기서 스샷을 따로 첨부하진 않겠지만 I펌→S펌, S펌→정펌 설치도 잘 됩니다. 모두 <code>sysupgrade</code> 명령어로 처리 가능합니다.(다만 후자의 경우 정펌엔 OpenWrt 메타데이터가 없기 때문에 <code>-F</code> 옵션을 추가해주어야 합니다.) OpenWrt에선 config 파티션에 손대지 않기 때문에 정펌으로 돌아가도 기존 설정은 그대로 유지될 것입니다.</p>
<p>아쉽게도 A604M은 리셋 버튼을 누른 상태에서 전원을 넣어도 TFTP 복구모드에 들어가지 않습니다. 강제로 복구모드에 진입하기 위해 정펌 업데이트 중간에 전원을 끄는 방법도 있긴 하지만 이건 남한테 추천은 못 하겠네요.</p>
<p>마지막으로 이미지 Makefile을 한번 보고 가도록 하겠습니다. dts가 하드웨어 정보를 모아놓은 곳이라면, <code>image/Makefile</code>은 이미지 생성방법이 적힌 곳입니다.</p>
<img src="/2020/08/22/openwrt-add-new-device/052-image-makefile.png" class="">
<ul>
<li><code>IMAGE_SIZE</code>는 펌웨어의 최대 크기를 지정합니다. 그냥 firmware 파티션 크기를 적어주면 됩니다.</li>
<li><code>DEVICE_PACKAGES</code>는 이미지에 포함될 기본 패키지를 지정합니다. 플래시 공간을 절약하기 위해선 단순히 있으면 좋은 정도가 아니라 기본 작동에 필수적인 것들만 포함시켜야 합니다.</li>
<li>이미지 종류나 생성방법을 바꾸려면 <code>IMAGES</code>나 <code>IMAGE/<image></code>를 설정하면 되는데, A604M의 경우엔 기본 I펌과 S펌만으로도 충분하므로 <code>factory.bin</code> 관련 설정은 지웁니다.</li>
<li><code>SUPPORTED_DEVICES</code>는 특수한 사정이 없으면 기본값을 쓰면 되므로 뺍니다.</li>
</ul>
<h1 id="메인라이닝">메인라이닝<a class="header-anchor" href="#메인라이닝"></a></h1>
<p>여태까지의 코드를 하나의 패치로 만들면 이렇게 됩니다. <a href="/2020/08/22/openwrt-add-new-device/v21.02.0-a604m.diff" title="v21.02.0-a604m.diff">v21.02.0-a604m.diff</a></p>
<p>이 패치를 혼자 사용하거나 개인 리포지토리에 올리고 끝내는 것도 방법이지만, 만약 OpenWrt 공식 저장소에 넣을 수 있다면 더 많은 사람들이 지원 패치의 혜택을 볼 수 있겠죠.</p>
<p>업스트림 저장소에 패치를 머지했을 때 좋은 점을 몇 가지 들어보자면,</p>
<ul>
<li><span class="exturl" data-url="aHR0cHM6Ly9idWlsZGJvdC5vcGVud3J0Lm9yZy8=">공식 빌드봇<i class="fa fa-external-link-alt"></i></span>이 이미지를 자동으로 빌드해주므로 직접 빌드할 필요가 없습니다.</li>
<li>만약 직접 빌드한 이미지를 쓴다면, 일반 패키지는 opkg로 다운로드받아 설치할 수 있지만, 커널 모듈만큼은 다운로드받아 쓸 수 없고 다시 빌드해 넣어야합니다. 이는 커널 빌드 옵션이 달라서 생기는 일으로, 공식 빌드봇과 같은 옵션을 줘서 빌드하면 해결되긴 하지만 이는 시간이 꽤 오래 걸리는 일입니다. 만약 패치에 커널 옵션 변경사항이 있다면 그마저도 불가능하고요.</li>
<li>공식 저장소에 머지되고 나면 로컬에서 업스트림 버전 업데이트를 따라갈 필요가 없다는 건 당연하겠죠.</li>
</ul>
<p>다만 패치가 "hack"에 가깝거나, 다른 모델에 부작용을 끼치거나, 코드 관리 부담이 큰 경우엔 머지가 거부될 수 있습니다.</p>
<p>현재 OpenWrt는 패치를 <span class="exturl" data-url="aHR0cHM6Ly9saXN0cy5vcGVud3J0Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL29wZW53cnQtZGV2ZWw=">메일링 리스트<i class="fa fa-external-link-alt"></i></span>나 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL29wZW53cnQvb3BlbndydC9wdWxscw==">GitHub<i class="fa fa-external-link-alt"></i></span>에서 받고 있습니다.<sup class="footnote-ref"><a href="#fn6" id="fnref6">[6]</a></sup> OpenWrt 메인테이너 중에는 커널 개발자도 많아서 패치 처리 절차도 비슷하게 따라가는 것 같습니다.</p>
<p>이 글에서 GitHub PR 여는 법을 설명하진 않겠지만, 대신 몇 가지 주의사항을 언급하자면,</p>
<ul>
<li>많은 오픈소스 프로젝트에서 패치를 어떻게 작성해야 하는지 가이드라인을 제시합니다. OpenWrt의 경우에도 마찬가지로 <span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9zdWJtaXR0aW5nLXBhdGNoZXM=">공식 가이드<i class="fa fa-external-link-alt"></i></span>에 따라 패치의 형식을 맞춰주어야 합니다.</li>
<li>다른 리뷰어의 질문과 코멘트에 적절히 응답해야 합니다. 나는 작동하는 패치를 줬으니 너희들이 알아서 고쳐서 넣어라, 식으로 나오는 사람이 가끔 있는데 이러면 머지될 확률이 낮아집니다.</li>
<li>대부분의 오픈소스 프로젝트가 그렇듯이, PR은 <span class="exturl" data-url="aHR0cHM6Ly9lZHlraW0uY29tL2tvL3Bvc3Qvb3Blbi1zb3VyY2UtbWFpbnRhaW5lcnMtb3dlLXlvdS1ub3RoaW5nLw==">관리자의 선의<i class="fa fa-external-link-alt"></i></span>로 머지됩니다. 특히 기기 지원 패치는 머지되기까지 몇 주 걸리는 게 보통입니다. PR에 아무런 반응이 달리지 않고 시간만 지나가는 데에 실망감이 드는 건 전혀 이상한 일이 아닙니다. 그렇지만 인내심을 갖고 기다리면서 가끔씩 관련자를 호출하는 것 외에 달리 할 수 있는 게 있는 것도 아닙니다.</li>
</ul>
<p>당연하다면 당연한 얘기지만 이것도 지키지 못해 거부되는 PR을 몇 번 봤기 때문에 노파심에 언급해둡니다…</p>
<p>운이 좋아 PR이 머지가 된다면 축하드립니다! 하루이틀 지나면 <span class="exturl" data-url="aHR0cHM6Ly9kb3dubG9hZHMub3BlbndydC5vcmcv">공식 다운로드 서버<i class="fa fa-external-link-alt"></i></span>나 <span class="exturl" data-url="aHR0cHM6Ly9maXJtd2FyZS1zZWxlY3Rvci5vcGVud3J0Lm9yZy8=">OFS<i class="fa fa-external-link-alt"></i></span>에서 이미지를 다운받을 수 있을 겁니다.</p>
<p>이 또한 의무는 아니지만(패치는 기여자의 선의로 작성됩니다), 머지 이후에도 당분간 기기를 처분하지 말고 혹시 들어올지 모르는 버그 제보에 대비하면 더욱 좋을 것 같습니다.</p>
<div class="note info"><p>참고문서:</p>
<ul>
<li><span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9zdWJtaXR0aW5nLXBhdGNoZXM=">[OpenWrt wiki] Submitting patches<i class="fa fa-external-link-alt"></i></span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL2d1aWRlLWRldmVsb3Blci9kZXZpY2Utc3VwcG9ydC1wb2xpY2llcw==">[OpenWrt wiki] Device support policies / best practices<i class="fa fa-external-link-alt"></i></span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly9vcGVud3J0Lm9yZy9kb2NzL2d1aWRlLWRldmVsb3Blci9mcmVxdWVudC1wci1taXN0YWtlcw==">[OpenWrt wiki] Frequent PR mistakes or “How to prevent my PR from getting delayed for sure”<i class="fa fa-external-link-alt"></i></span></li>
</ul>
</div>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>이제 ar71xx 타겟은 master 브랜치에서 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL29wZW53cnQvb3BlbndydC9jb21taXQvNGU0ZWU0NjQ5NTUzYWI1MzYyMjUwNjBhMjdmYzMyMGJmNTRlNDU4Yw==">제거<i class="fa fa-external-link-alt"></i></span>되었기 때문에 앞으론 ath79 타겟을 써야합니다. <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>NOR 플래시 이미지에 해당하는 얘기고, NAND 플래시나 SD카드 이미지는 구조가 조금 다릅니다. <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>A604M에서 SOIC 클립으로 온보드 플래시 덤프가 가능한 걸 확인했습니다. 여기까지 시도하실 분이라면 제가 뭐라 덧붙이지 않아도 어련히 잘 하시겠죠. <a href="#fnref3" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>그럼 만약 동일한 칩셋이 두 개라면요? 그런 경우라도 보통 2.4GHz용 하나, 5GHz용 하나, 이런 식이기 때문에 캘값을 바꿔 넣으면 일단 인식은 되는데 정작 WiFi 신호가 안 잡힐 겁니다. 그럼 세 개라면요? …그만합시다. <a href="#fnref4" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn5" class="footnote-item"><p>그 외에도 메모리 크기, 주변장치 종류, 스위치 포트 순서도 알려주는 아주 좋은 자료입니다. <a href="#fnref5" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>나중에 자체운영 GitLab으로 넘어갈 거라곤 하는데 아직은 별다른 소식이 없네요. <a href="#fnref6" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content>
<categories>
<category>자유시간 프로젝트</category>
</categories>
<tags>
<tag>분해</tag>
<tag>OpenWrt</tag>
<tag>포팅</tag>
</tags>
</entry>
<entry>
<title>DW02-412H 작업기: eth1 살리기</title>
<url>/2022/08/14/dw02-412h-enable-eth1/</url>
<content><![CDATA[<div class="note "><p>DW02-412H 작업기 시리즈</p>
<ol>
<li>OpenWrt 포팅 따라하기</li>
<li>ath79로 재포팅</li>
<li><strong>eth1 살리기</strong></li>
<li>qca8k로 넘어가기</li>
</ol>
</div>
<span id="more"></span>
<p>※ 이 글은 2020년 7월에 작업했던 내용을 당시의 기록과 기억에 기반해 정리한 것이고, 포스팅 내의 모든 이미지는 글을 작성하는 시점에서 새로 생성하였습니다.</p>
<h2 id="포팅-후-남은-찜찜함">포팅 후 남은 찜찜함<a class="header-anchor" href="#포팅-후-남은-찜찜함"></a></h2>
<p>OpenWrt 포팅 작업은 끝났고 웬만한 기능은 다 살린 것 같지만… 찜찜함이 하나 남습니다.</p>
<p><img src="001-swconfig-link.png" alt="swconfig link"></p>
<p>저 port 6은 대체 뭘까요? 왜 10Mbps로 연결되어 있다고 하죠? (물론 이더넷 케이블은 하나도 꽂지 않은 상태입니다)</p>
<p>DW02의 내부 네트워크 토폴로지를 복습해봅시다. (VLAN이나 브리지는 잠시 무시합니다)</p>
<p><img src="002-network-diagram.png" alt="DW02 내부 구성도"></p>
<p>QCA9557 SoC는 두 개의 이더넷 인터페이스(eth0과 eth1)를 지원하고 QCA8337N 스위치는 7개의 이더넷 포트(5개는 랜선과 연결되는 포트, 2개는 CPU와 연결되는 포트)를 지원합니다. DW02에 달린 RJ45 포트는 5개뿐이니 port 6이 외부와 연결됐을 리는 없고, 상식적으로 CPU의 eth1 인터페이스와 연결되었다고 추측하는 게 가장 그럴듯하겠죠?</p>
<p>하지만 ar71xx에서도 ath79에서도 이더넷/스위치 설정을 이리저리 바꿔봤었지만 링크를 활성화시키는 데는 결국 실패했고, 정말 eth1이 port 6에 연결된 게 맞는지조차 알쏭달쏭한 상태에서 포기했었습니다. 어쨌든 이거 없어도 유선랜은 잘 되니까요.</p>
<p>그러다가 DW03-608H 포팅을 하면서 스위치에 대한 이해도가 조금 더 올라가고 나니 이 미제에 다시 도전해볼 용기가 생겼습니다. DW03에서 QCA8337<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> 스위치에 eth0과 eth1이 모두 연결된 걸 확인하고 둘 다 활성화하는 데 성공했는데, DW02에도 같은 방법을 적용하면 마찬가지로 eth1이 뚫릴 거라는 기대가 생긴 거죠.</p>
<h2 id="링크-존재-확인">링크 존재 확인<a class="header-anchor" href="#링크-존재-확인"></a></h2>
<p>먼저 CPU와 스위치 사이에 회로상 연결이 존재하는지부터 확인해볼까요. QCA8337N의 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL0Rlb3B0aW0vYXRoZXJvcy9ibG9iL21hc3Rlci9RQ0E4MzM3Tl9EYXRhX1NoZWV0X01LRy0xNzc5M192MS4wLnBkZg==">데이터시트<i class="fa fa-external-link-alt"></i></span>에서 핀아웃 그림을 봅시다.</p>
<p><img src="003-qca8337n-pinout.png" alt="스위치 핀아웃"></p>
<p>QCA8337N에는 CPU 포트를 위한 인터페이스로 RGMII 두 개와 SGMII 한 개가 있습니다.<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup> 빨갛게 표시한 핀이 RGMII #0, 녹색으로 표시한 핀이 RGMII #1, 파랗게 표시한 핀이 SGMII입니다.</p>
<p>이걸 실제 보드의 PCB 패턴과 비교해보겠습니다.</p>
<p><img src="004-qca8337n-trace.jpg" alt="스위치 트레이스"></p>
<p>트레이스가 뻗어나온 핀은 RGMII #0와 SGMII입니다. 보드 앞면만 봐선 이게 정말 SoC까지 이어져 있는지 알 수 없지만 (여기선 생략한) 뒷면도 보면 대략 짐작할 수 있습니다. 짐작만으로 끝내는 이유는… SoC가 BGA라서요.</p>
<h2 id="스위치-설정">스위치 설정<a class="header-anchor" href="#스위치-설정"></a></h2>
<p>자, 그럼 회로 연결은 됐다고 치고, 이제 SGMII 설정 작업에 들어가보겠습니다.</p>
<p>일단 확인 차원에서 부팅 중 ar8xxx 스위치 드라이버에서 스위치 레지스터를 덤프해봤는데 특별히 눈에 띄는 건 없네요.</p>
<p><img src="005-qca8337n-dump.png" alt="스위치 레지스터 덤프"></p>
<p>저번에 DW03에서 SGMII를 켜기 위해 건드려줬던 스위치 레지스터는 다음과 같습니다.</p>
<ul>
<li>PORT6_PAD_CTRL</li>
<li>PWS_REG (특히 SERDES_AEN 비트)</li>
<li>PORT6_STATUS</li>
<li>SGMII_CTRL</li>
</ul>
<p>여기서도 똑같이 설정해주면 되겠죠.</p>
<figure class="highlight dts"><figcaption><span>qca9557_dongwon_dw02-412h.dts</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="variable">&mdio0</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">status</span> <span class="operator">=</span> <span class="string">"okay"</span><span class="punctuation">;</span></span><br><span class="line"></span><br><span class="line"> <span class="title class_">switch@0</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">reg</span> <span class="operator">=</span> <span class="params"><<span class="number">0x0</span>></span><span class="punctuation">;</span></span><br><span class="line"> qca,ar8327-<span class="attr">initvals</span> <span class="operator">=</span> <span class="params"><</span></span><br><span class="line"><span class="params"> <span class="number">0x0004</span> <span class="number">0x07600000</span> /* PORT0_PAD_CTRL */</span></span><br><span class="line"><span class="params"> <span class="number">0x000c</span> <span class="number">0x00000080</span> /* PORT6_PAD_CTRL */</span></span><br><span class="line"><span class="params"> /* PWS_REG는 DW02에서 초깃값과 설정값이 동일하여 생략 */</span></span><br><span class="line"><span class="params"> <span class="number">0x007c</span> <span class="number">0x0000007e</span> /* PORT0_STATUS */</span></span><br><span class="line"><span class="params"> <span class="number">0x0094</span> <span class="number">0x0000007e</span> /* PORT6_STATUS */</span></span><br><span class="line"><span class="params"> <span class="number">0x00e0</span> <span class="number">0xc74164de</span> /* SGMII_CTRL */</span></span><br><span class="line"><span class="params"> ></span><span class="punctuation">;</span></span><br><span class="line"> <span class="punctuation">};</span></span><br><span class="line"><span class="punctuation">};</span></span><br></pre></td></tr></table></figure>
<p>eth1도 켜주고요.</p>
<figure class="highlight dts"><figcaption><span>qca9557_dongwon_dw02-412h.dts</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="variable">&eth1</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">status</span> <span class="operator">=</span> <span class="string">"okay"</span><span class="punctuation">;</span></span><br><span class="line"></span><br><span class="line"> <span class="attr">pll-data</span> <span class="operator">=</span> <span class="params"><<span class="number">0x03000101</span> <span class="number">0x00000101</span> <span class="number">0x00001616</span>></span><span class="punctuation">;</span></span><br><span class="line"> qca955<span class="attr">x-sgmii-fixup</span><span class="punctuation">;</span> <span class="comment">// SGMII 링크 재시작</span></span><br><span class="line"> <span class="attr">mtd-mac-address</span> <span class="operator">=</span> <span class="params"><<span class="variable">&art</span> <span class="number">0x6</span>></span><span class="punctuation">;</span></span><br><span class="line"></span><br><span class="line"> <span class="title class_">gmac-config</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">device</span> <span class="operator">=</span> <span class="params"><<span class="variable">&gmac</span>></span><span class="punctuation">;</span></span><br><span class="line"> ge0-<span class="attr">sgmii</span> <span class="operator">=</span> <span class="params"><<span class="number">0</span>></span><span class="punctuation">;</span> <span class="comment">// eth0이 RGMII, eth1이 SGMII</span></span><br><span class="line"> <span class="punctuation">};</span></span><br><span class="line"></span><br><span class="line"> <span class="title class_">fixed-link</span> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">speed</span> <span class="operator">=</span> <span class="params"><<span class="number">1000</span>></span><span class="punctuation">;</span> <span class="comment">// CPU와 스위치를 잇는 포트는 고정 속도로 두는 것이 관례</span></span><br><span class="line"> <span class="attr">full-duplex</span><span class="punctuation">;</span></span><br><span class="line"> <span class="punctuation">};</span></span><br><span class="line"><span class="punctuation">};</span></span><br></pre></td></tr></table></figure>
<p>eth1으로 패킷이 잘 오가는지 확인하기 위해 잠시 eth0을 VLAN에서 빼고 eth1으로만 트래픽을 몰아줍니다.</p>
<figure class="highlight sh"><figcaption><span>02_network</span></figcaption><table><tr><td class="code"><pre><span class="line">dongwon,dw02-412h)</span><br><span class="line"> ucidef_add_switch <span class="string">"switch0"</span> \</span><br><span class="line"> <span class="string">"2:lan:4"</span> <span class="string">"3:lan:3"</span> <span class="string">"4:lan:2"</span> <span class="string">"5:lan:1"</span> <span class="string">"1:wan"</span> <span class="string">"6@eth1"</span> <span class="comment"># "0@eth0"</span></span><br><span class="line"> ;;</span><br></pre></td></tr></table></figure>
<p>DW03에선 이쯤에서 성공했었는데…</p>
<p><img src="006-eth1-ping-fail.png" alt="여전히 막힌 eth1"></p>
<p>ping도 안 가네요. 아직 뭔가 빼먹은 게 있나 봅니다.</p>
<h2 id="SoC-설정">SoC 설정<a class="header-anchor" href="#SoC-설정"></a></h2>
<p>스위치에서 눈을 돌려 SoC 쪽을 살펴봅시다. SoC에도 SGMII 설정에 관여하는 레지스터가 몇 있습니다.</p>
<p><img src="007-sgmii-config-reg.png" alt="SGMII_CONFIG 레지스터"></p>
<p>QCA9558 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL0Rlb3B0aW0vYXRoZXJvcy9ibG9iL21hc3Rlci9RQ0E5NTU4X25vd2F0ZXJtYXJrLnBkZg==">데이터시트<i class="fa fa-external-link-alt"></i></span><sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>를 보면 SGMII_CONFIG란 레지스터가 있는데요. 이름만 들어봐도 중요할 것 같죠?</p>
<p><img src="008-sgmii-config-read.png" alt="SGMII_CONFIG 값 읽어보기"></p>
<p>근데 해당 레지스터 값을 읽어보니 텅 비어있네요. 데이터시트와 비트 필드를 비교해봤을 때 0x00000000이 제대로 된 세팅값은 아닐 것 같은데요.</p>
<p>그러면 드라이버에서 SGMII_CONFIG 레지스터 설정을 해줘야 할 텐데, 검색해보니 해당 주소 매크로만이 정의되어 있을 뿐, 이 레지스터에 접근하는 코드는 아예 존재하지 않습니다.<sup class="footnote-ref"><a href="#fn4" id="fnref4">[4]</a></sup></p>
<p><img src="009-sgmii-config-grep.png" alt="SGMII_CONFIG 관련 코드"></p>
<p>흠… 보통은 부트로더가 알아서 설정해줘서 드라이버에서 따로 건드릴 필요를 못 느꼈던 걸까요? 하여간 여기선 제가 수동으로 켜줘야겠죠. 이럴 때 레퍼런스 코드가 있으면 참 도움이 될 텐데, DW02 소스코드는 제게 없으니 대신 하드웨어가 적당히 비슷한 다른 모델의 GPL 소스를 참고해봐야겠네요.</p>
<p>TP-Link <span class="exturl" data-url="aHR0cHM6Ly93aWtpZGV2aS53aS1jYXQucnUvVFAtTElOS19BcmNoZXJfQzdfdjEueA==">Archer C7 v1<i class="fa fa-external-link-alt"></i></span>의 U-Boot <span class="exturl" data-url="aHR0cHM6Ly93d3cudHAtbGluay5jb20vdXMvc3VwcG9ydC9kb3dubG9hZC9hcmNoZXItYzcvdjEvI0dQTC1Db2Rl">소스<i class="fa fa-external-link-alt"></i></span>에서 SGMII_CONFIG 레지스터를 설정하는 코드를 발견했습니다. (좀 길어서 적당히 간추려서 발췌했습니다.)</p>
<figure class="highlight c"><figcaption><span>qca-eth-955x.c</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="type">static</span> <span class="type">void</span> <span class="title function_">athr_gmac_sgmii_setup</span><span class="params">()</span></span><br><span class="line">{</span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> ATH_SGMII_FORCED_MODE</span></span><br><span class="line"> REG_WRITE(MR_AN_CONTROL, <span class="number">0x8140</span>);</span><br><span class="line"> REG_WRITE(SGMII_CONFIG, <span class="number">0xa2</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line"> REG_WRITE(SGMII_CONFIG, <span class="number">0x02</span>);</span><br><span class="line"> REG_WRITE(MR_AN_CONTROL, <span class="number">0x9000</span>);</span><br><span class="line"> REG_WRITE(MR_AN_CONTROL, <span class="number">0x1000</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"> <span class="comment">/* SGMII reset sequence */</span></span><br><span class="line"> REG_WRITE(SGMII_RESET, <span class="number">0x00</span>);</span><br><span class="line"> REG_WRITE(SGMII_RESET, <span class="number">0x10</span>);</span><br><span class="line"> REG_WRITE(SGMII_RESET, <span class="number">0x14</span>);</span><br><span class="line"> REG_WRITE(SGMII_RESET, <span class="number">0x1c</span>);</span><br><span class="line"> REG_WRITE(SGMII_RESET, <span class="number">0x1d</span>);</span><br><span class="line"> REG_WRITE(SGMII_RESET, <span class="number">0x1f</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* Check SGMII link status */</span></span><br><span class="line"> REG_CLEAR(MR_AN_CONTROL, <span class="number">0x8000</span>);</span><br><span class="line"> status = (REG_READ(SGMII_DEBUG) & <span class="number">0xff</span>);</span><br><span class="line"> <span class="keyword">while</span> (!(status == <span class="number">0xf</span> || status == <span class="number">0x10</span>)) {</span><br><span class="line"> REG_SET(MR_AN_CONTROL, <span class="number">0x8000</span>);</span><br><span class="line"> REG_CLEAR(MR_AN_CONTROL, <span class="number">0x8000</span>);</span><br><span class="line"> <span class="keyword">if</span> (count++ == MAX_TRY)</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> status = (REG_READ(SGMII_DEBUG) & <span class="number">0xff</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>이걸 쉘에서 따라해보니… 드디어 ping이 가네요!</p>
<p><img src="010-sgmii-config-write.png" alt="SGMII_CONFIG 설정"></p>
<p>코드에 따르면 SGMII_DEBUG 레지스터 값이 0xf 또는 0x10이어야 한다는데 저는 0x8이 뜨네요. SGMII_DEBUG는 데이터시트에도 안 나와있는 숨겨진 레지스터라 무슨 뜻인지도 모르겠고…</p>
<p>암튼 이제 이걸 ag71xx 이더넷 드라이버에 집어넣어봅시다. SGMII_RESET과 SGMII_DEBUG 레지스터에 접근하는 코드는 ag71xx 드라이버에도 이미 있는데, 처음에 MR_AN_CONTROL와 SGMII_CONFIG 레지스터를 설정하는 코드는 드라이버에 없으니 이 부분만 끼워넣어주면 되겠죠.</p>
<figure class="highlight diff"><figcaption><span>ag71xx_main.c</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="meta">@@ -605,6 +605,20 @@</span> static void ag71xx_sgmii_init_qca955x(struct device_node *np)</span><br><span class="line"> if (!(mr_an_status & QCA955X_MR_AN_STATUS_AN_ABILITY))</span><br><span class="line"> goto sgmii_out;</span><br><span class="line"> </span><br><span class="line"><span class="addition">+ __raw_writel(QCA955X_MR_AN_CONTROL_PHY_RESET |</span></span><br><span class="line"><span class="addition">+ QCA955X_MR_AN_CONTROL_DUPLEX_MODE |</span></span><br><span class="line"><span class="addition">+ QCA955X_MR_AN_CONTROL_SPEED_SEL1,</span></span><br><span class="line"><span class="addition">+ gmac_base + QCA955X_GMAC_REG_MR_AN_CONTROL);</span></span><br><span class="line"><span class="addition">+ __raw_readl(gmac_base + QCA955X_GMAC_REG_MR_AN_CONTROL);</span></span><br><span class="line"><span class="addition">+ udelay(10);</span></span><br><span class="line"><span class="addition">+</span></span><br><span class="line"><span class="addition">+ __raw_writel(2 << QCA955X_SGMII_CONFIG_SPEED_SHIFT |</span></span><br><span class="line"><span class="addition">+ QCA955X_SGMII_CONFIG_FORCE_SPEED |</span></span><br><span class="line"><span class="addition">+ 2 << QCA955X_SGMII_CONFIG_MODE_CTRL_SHIFT,</span></span><br><span class="line"><span class="addition">+ gmac_base + QCA955X_GMAC_REG_SGMII_CONFIG);</span></span><br><span class="line"><span class="addition">+ __raw_readl(gmac_base + QCA955X_GMAC_REG_SGMII_CONFIG);</span></span><br><span class="line"><span class="addition">+ udelay(10);</span></span><br><span class="line"><span class="addition">+</span></span><br><span class="line"> /* SGMII reset sequence */</span><br><span class="line"> __raw_writel(QCA955X_SGMII_RESET_RX_CLK_N_RESET,</span><br><span class="line"> gmac_base + QCA955X_GMAC_REG_SGMII_RESET);</span><br><span class="line"><span class="meta">@@ -655,7 +669,7 @@</span> static void ag71xx_sgmii_init_qca955x(struct device_node *np)</span><br><span class="line"> pr_err("ag71xx: max retries for SGMII fixup exceeded\n");</span><br><span class="line"> break;</span><br><span class="line"> }</span><br><span class="line"><span class="deletion">- } while (!(sgmii_status == 0xf || sgmii_status == 0x10));</span></span><br><span class="line"><span class="addition">+ } while (!(sgmii_status == 0x8 || sgmii_status == 0xf || sgmii_status == 0x10));</span></span><br><span class="line"> </span><br><span class="line"> sgmii_out:</span><br><span class="line"> iounmap(gmac_base);</span><br></pre></td></tr></table></figure>
<div class="note info"><p>◈ 나중에 더 테스트해보고 알게 된 건데, 위의 변경사항 중에서 핵심은 SGMII_CONFIG에서의 고정 속도 설정입니다. 나머지는 빼도 잘 작동하네요.<br>
만약 스위치에서 SGMII 자동 속도 기능을 켜면(<code>SERDES_AEN := 0</code>) 이마저도 필요없게 되더라고요. 괜히 고생한 건가 싶기도 하고…</p>
</div>
<h2 id="성능-테스트">성능 테스트<a class="header-anchor" href="#성능-테스트"></a></h2>
<p>자, 이제 eth1이 살아났으니 두 CPU 포트를 동시에 쓸 수 있게 되었습니다.<br>
이게 무슨 의미냐면, LAN은 eth0, WAN은 eth1으로 연결해서 트래픽을 분산시킬 수 있다는 얘깁니다.</p>
<p><img src="011-uci-vlan.png" alt="VLAN 설정 확인"></p>
<p>스위치와 CPU 사이의 총 대역폭이 2Gbps로 늘어났으니 유선랜 속도가 더 빨라지겠죠?</p>
<p>먼저 iperf로 테스트해보는데… 어라? 예상만큼 속도가 안 나오네요.</p>
<div class="note info"><p>◈ 당시에 테스트했을 땐 eth1를 켜면 오히려 flow offloading 효과가 저하되는 걸로 나와 못 써먹겠다고 판단했었는데, 이 글을 쓰는 지금 다시 테스트해보니 조금 다른 결과가 나왔습니다.</p>
<p>아래는 iperf3로 DL(WAN->LAN)/UL(LAN->WAN) 속도 테스트를 한 결과입니다. (SW flow offloading 켬)</p>
<table>
<thead>
<tr>
<th></th>
<th style="text-align:right">TCP DL</th>
<th style="text-align:right">TCP UL</th>
<th style="text-align:right">UDP DL</th>
<th style="text-align:right">UDP UL</th>
</tr>
</thead>
<tbody>
<tr>
<td>eth0 LAN/WAN</td>
<td style="text-align:right">928 Mbps</td>
<td style="text-align:right">931 Mbps</td>
<td style="text-align:right">950 Mbps</td>
<td style="text-align:right">952 Mbps</td>
</tr>
<tr>
<td>eth1 LAN/WAN</td>
<td style="text-align:right">926 Mbps</td>
<td style="text-align:right">930 Mbps</td>
<td style="text-align:right">952 Mbps</td>
<td style="text-align:right">952 Mbps</td>
</tr>
<tr>
<td>eth0 LAN, eth1 WAN</td>
<td style="text-align:right">921 Mbps</td>
<td style="text-align:right">935 Mbps</td>
<td style="text-align:right">953 Mbps</td>
<td style="text-align:right">952 Mbps</td>
</tr>
<tr>
<td>eth1 LAN, eth0 WAN</td>
<td style="text-align:right">918 Mbps</td>
<td style="text-align:right">936 Mbps</td>
<td style="text-align:right">953 Mbps</td>
<td style="text-align:right">950 Mbps</td>
</tr>
</tbody>
</table>
<p>별로 차이가 없어 보이는데, 하긴 단방향 트래픽으론 병목이 안 생길 테니 이걸로 보면 안 되겠죠. <code>--bidir</code> 옵션을 걸고 다시 해보면,</p>
<table>
<thead>
<tr>
<th></th>
<th style="text-align:right">TCP (=DL+UL)</th>
<th style="text-align:right">UDP (=DL+UL)</th>
</tr>
</thead>
<tbody>
<tr>
<td>eth0 LAN/WAN</td>
<td style="text-align:right">889 Mbps (=442+447)</td>
<td style="text-align:right">950 Mbps (=475+475)</td>
</tr>
<tr>
<td>eth1 LAN/WAN</td>
<td style="text-align:right">897 Mbps (=454+443)</td>
<td style="text-align:right">948 Mbps (=474+474)</td>
</tr>
<tr>
<td>eth0 LAN, eth1 WAN</td>
<td style="text-align:right">926 Mbps (=485+441)</td>
<td style="text-align:right">1047 Mbps (=524+523)</td>
</tr>
<tr>
<td>eth1 LAN, eth0 WAN</td>
<td style="text-align:right">922 Mbps (=463+459)</td>
<td style="text-align:right">1055 Mbps (=528+527)</td>
</tr>
</tbody>
</table>
<p>이번엔 살짝 효과가 있는 것 같긴 한데, 그래도 전체 가용 대역폭에 비하면 여전히 한참 낮습니다.</p>
</div>
<p>혹시 <span class="exturl" data-url="aHR0cHM6Ly93aWtpLmxpbnV4Zm91bmRhdGlvbi5vcmcvbmV0d29ya2luZy9ib25kaW5n">bonding<i class="fa fa-external-link-alt"></i></span>을 쓰면 속도를 더 내주려나 하고 써봤는데,</p>
<p><img src="012-iperf-over-bond0.png" alt="eth0/eth1을 bond0로 묶고 iperf"></p>
<p>eth1을 켜니 오히려 느려지네요. 에라이.</p>
<p>이거 아무래도 병목이 IO가 아니라 CPU에 있나본데요. 애초에 CPU가 느린 거라면 대역폭을 늘려도 제대로 활용하기 어려울 것 같네요. DW02에서도 HW NAT를 쓸 수 있게 되는 날이 어서 오기를 기원해봅시다.</p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>뒤에 N이 붙고 안 붙고 차이는 HW NAT 기능 여부뿐이라고 합니다. <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>RGMII와 SGMII란 걸 처음 들어보셨다면 <span class="exturl" data-url="aHR0cHM6Ly9kb2trb2RhaS50aXN0b3J5LmNvbS8xNzY=">여기<i class="fa fa-external-link-alt"></i></span>에 나오는 그림을 참고하시면 이해에 도움이 될 듯 합니다. <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>QCA9557 데이터시트를 못 찾겠어서 대신 WLAN이 3x3이라는 것만 빼면 동일할 것으로 추측되는 QCA9558 데이터시트를 보겠습니다. <a href="#fnref3" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn4" class="footnote-item"><p><div class="note info"><p>◈ 참고로 나중에 SGMII_CONFIG 레지스터를 설정하는 코드가 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL29wZW53cnQvb3BlbndydC9jb21taXQvZmJiYWQ5YTlhNjI5YjM4ODYyNmI0NzdlNmNkNjkyYzE2MGY2M2ZiMw==">한번<i class="fa fa-external-link-alt"></i></span> 추가되긴 했지만, 이건 qca956x가 대상일뿐더러 MODE_CTRL 외의 필드엔 접근하지 않습니다.</p>
</div> <a href="#fnref4" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content>
<categories>
<category>자유시간 프로젝트</category>
</categories>
<tags>
<tag>OpenWrt</tag>
</tags>
</entry>
<entry>
<title>DIY Wi-Fi 6E AP</title>
<url>/2023/01/24/diy-6ghz-ap/</url>
<content><![CDATA[<p>※ 2023-09-17: QCNFA765 테스트 내용 추가</p>
<h2 id="서론">서론<a class="header-anchor" href="#서론"></a></h2>
<p>Wi-Fi 6E가 <span class="exturl" data-url="aHR0cHM6Ly93d3cud2ktZmkub3JnL25ld3MtZXZlbnRzL25ld3Nyb29tL3dpLWZpLWFsbGlhbmNlLWJyaW5ncy13aS1maS02LWludG8tNi1naHo=">발표<i class="fa fa-external-link-alt"></i></span>된 지도 어언 3년.</p>
<p>그냥 6GHz 대역을 한번 써보고 싶었습니다. 실사용 목적이라기보단 호기심에 가까운 편이라 가급적 저렴하게 Wi-Fi 6E 네트워크를 구성해보려고 했습니다.</p>
<span id="more"></span>
<ul>
<li>AP: 시중의 비교적 저렴한<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> Wi-Fi 6E AP는 브로드컴 칩셋을 쓰는 것 같은데, OpenWrt를 올려서 쓰기엔 지원이 아직 부족합니다. 커펌을 포기하고 구매할 정도로 가성비가 훌륭한가 하면 제 입장에선 아닌 것 같네요.</li>
<li>스마트폰 핫스팟: 아쉽게도 지금 제가 사용하는 스마트폰은 Wi-Fi 6E를 지원하지 않습니다. 이거 하나 때문에 플래그십 스마트폰을 새로 들일 생각은 없고요.</li>
<li>PC 핫스팟: Wi-Fi 6E 무선랜카드가 그럭저럭 저렴한데요.<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup> SoftAP가 되는지가 관건이겠습니다.</li>
</ul>
<p>제가 알아본 6GHz 대역 무선랜카드 목록은 다음과 같습니다. (여기 있는게 전부는 아닙니다!)</p>
<ul>
<li>M.2 (CNVi 제외)
<ul>
<li>Intel: AX210NGW(WCSAX210)</li>
<li>MediaTek: RZ608(MT7921K), RZ616(MT7922A)</li>
<li>Qualcomm: <span class="exturl" data-url="aHR0cHM6Ly93d3cuYWN3aWZpLm5ldC8yMTk5NC5odG1s">QCNFA765<i class="fa fa-external-link-alt"></i></span>(WCN6856), WNFQ-268AXI(WCN6856), WMX7205(WCN6856)</li>
</ul>
</li>
<li>mPCIe (AP급 성능)
<ul>
<li>MediaTek: <span class="exturl" data-url="aHR0cHM6Ly93d3cuYXNpYXJmLmNvbS9zaG9wL3dpZmktd2xhbi93aWZpX21pbmlfcGNpZS93aWZpNmUtMzAwMC04MDItMTFheC0zdDNyLWRiZGMtbXBjaWUv">AW7916-NPD<i class="fa fa-external-link-alt"></i></span>(MT7916AN)</li>
<li>Qualcomm: WPEQ-276AX(QCN9072), WMX7406(QCN9074), Pineapple 6(QCN9074)</li>
</ul>
</li>
<li>USB
<ul>
<li>MediaTek: CF-953AX(MT7921AU), A8000(MT7921AU), <span class="exturl" data-url="aHR0cHM6Ly93d3cuYWxmYS5jb20udHcvcHJvZHVjdHMvYXd1czAzNmF4bWw/dmFyaWFudD0zOTc1NDM2MDY4NDYxNg==">AWUS036AXML<i class="fa fa-external-link-alt"></i></span>(MT7921AU)</li>
</ul>
</li>
</ul>
<p>이 중에서 제가 선택한 건 AX210NGW와 MT7922A22M<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>입니다. 선택한 이유는,</p>
<ul>
<li>AX210NGW: 평범하게 실사용하기엔 가장 무난하다고 봅니다. 사실 2021년 초에 알아봤을 땐 이것밖에 선택지가 없었습니다.</li>
<li>MT7922A22M: 드라이버 면에서 ath11k보단 mt76이 더 친숙했고, USB보단 PCIe가 더 안정적일 것 같았고, AW7916-NPD도 끌리긴 했지만 그렇게까지 본격적으로 써볼 생각은 아니어서 단념했고, <span class="exturl" data-url="aHR0cHM6Ly8yNHdpcmVsZXNzLmluZm8vd2lmaS02LW1vZHVsZS1mb3ItcGM=">MT7921과 달리<i class="fa fa-external-link-alt"></i></span> MT7922는 160MHz 채널폭을 지원한다고 하는데 가격도 알리 기준으로 2만원 정도로 적당해서 골랐습니다.</li>
</ul>
<p>검색해보니 CF-953AX에서 6GHz AP를 켜는 데 성공한 사례가 있네요.</p>
<ul>
<li><span class="exturl" data-url="aHR0cHM6Ly9jb21tdW5pdHkuZnJhbWUud29yay90L21haW5ib2FyZC1hcy1pbnRlcm5ldC1yb3V0ZXItd2lyZWxlc3MtYXAtbmFzLXByb2plY3QvMTgyNzIvNDM=">CF-953AX & MT7921K<i class="fa fa-external-link-alt"></i></span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL21vcnJvd25yL1VTQi1XaUZpL2lzc3Vlcy8xMDMjaXNzdWVjb21tZW50LTEzMjA5NjAzOTQ=">CF-953AX & WCN685x<i class="fa fa-external-link-alt"></i></span></li>
</ul>
<p>아래서 AX210NGW, MT7922A22M, QCNFA765의 줄임말로 각각 AX210, MT7922, NFA765를 사용하겠습니다.</p>
<h2 id="AX210">AX210<a class="header-anchor" href="#AX210"></a></h2>
<p>AX210 구매 당시엔 단순히 인텔 무선랜카드에선 AP 모드를 지원 안 한다 정도로만 알고 있었는데,<sup class="footnote-ref"><a href="#fn4" id="fnref4">[4]</a></sup> 실상은 더 복잡했습니다.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">$ iw phy phy0 info | grep -A8 "Supported interface modes:"</span><br><span class="line"> Supported interface modes:</span><br><span class="line"> * IBSS</span><br><span class="line"> * managed</span><br><span class="line"> * AP</span><br><span class="line"> * AP/VLAN</span><br><span class="line"> * monitor</span><br><span class="line"> * P2P-client</span><br><span class="line"> * P2P-GO</span><br><span class="line"> * P2P-device</span><br></pre></td></tr></table></figure>
<p>AX210은 (여타 인텔 AC/AX 무선랜카드와 마찬가지로) AP 모드를 지원합니다. 문제가 되는 것은 AX210에는 (여타 인텔 AC/AX 무선랜카드와 마찬가지로) 펌웨어에 박혀있어 비활성화할 수 없는 <span class="exturl" data-url="aHR0cHM6Ly93aWtpLmFyY2hsaW51eC5vcmcvdGl0bGUvc29mdHdhcmVfYWNjZXNzX3BvaW50I0Nhbm5vdF9zdGFydF9BUF9tb2RlX2luXzVfR0h6X2JhbmQ=">LAR(Location-Aware Regulatory)<i class="fa fa-external-link-alt"></i></span>이란 기능이 내장되어 있다는 것입니다.</p>
<p>이것이 무엇 하는 기능인고 하니, 주위의 Wi-Fi AP 신호를 들어보고 자신의 국가 위치를 감지하여<sup class="footnote-ref"><a href="#fn5" id="fnref5">[5]</a></sup> 해당 국가의 전파규제를 적용하는 기능입니다. 이때 적용되는 주파수 및 출력 제한은 운영체제에서 제공하는 정보가 아니라 펌웨어에 포함된 자체 데이터베이스를 기반으로 합니다. 아래 로그를 보면 phy0에 "self-managed"가 붙어있는데, 리눅스 커널의 wireless-regdb와 별도의 정책을 따른다는 뜻입니다.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">$ iw reg get | grep -C1 country</span><br><span class="line">global</span><br><span class="line">country KR: DFS-JP</span><br><span class="line"> (2400 - 2483 @ 40), (N/A, 23), (N/A)</span><br><span class="line">--</span><br><span class="line">phy#0 (self-managed)</span><br><span class="line">country KR: DFS-UNSET</span><br><span class="line"> (2402 - 2437 @ 40), (6, 22), (N/A), AUTO-BW, NO-HT40MINUS, NO-80MHZ, NO-160MHZ</span><br></pre></td></tr></table></figure>
<p>인텔은 국가별 전파규제를 최대한 지키기 위해 LAR을 도입했겠지만, 국가 감지가 제대로 되지 않거나 실제 법규와 다르게 작동한다면 사용자 입장에서 곤란할 수 있겠죠. 전자는 5GHz AP를 켤 때 문제가 되고, 후자는 6GHz AP를 켤 때 문제가 됩니다.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">$ iw phy phy0 info | grep -A1 "Frequencies"</span><br><span class="line"> Frequencies:</span><br><span class="line"> * 2412 MHz [1] (22.0 dBm)</span><br><span class="line">--</span><br><span class="line"> Frequencies:</span><br><span class="line"> * 5180 MHz [36] (22.0 dBm)</span><br><span class="line">--</span><br><span class="line"> Frequencies:</span><br><span class="line"> * 5955 MHz [1] (22.0 dBm) (no IR)</span><br></pre></td></tr></table></figure>
<p><span class="exturl" data-url="aHR0cHM6Ly9naXQua2VybmVsLm9yZy9wdWIvc2NtL2xpbnV4L2tlcm5lbC9naXQvZmlybXdhcmUvbGludXgtZmlybXdhcmUuZ2l0L2NvbW1pdC9pd2x3aWZpLXR5LWEwLWdmLWEwLnBudm0/aWQ9NDQ3NDUxOWExZmQ0ZTcxNjdhZmFlN2M1Y2EyYzFiOTNlMTdiNGQ4YQ==">AX210 펌웨어<i class="fa fa-external-link-alt"></i></span>는 한국 지역에서 6GHz 대역을 활성화한 상태고, station(STA) 모드로는 별다른 문제 없이 사용 가능합니다. 문제는 이렇게 활성화된 6GHz 채널에 "<span class="exturl" data-url="aHR0cHM6Ly93aXJlbGVzcy53aWtpLmtlcm5lbC5vcmcvZW4vZGV2ZWxvcGVycy9yZWd1bGF0b3J5L3Byb2Nlc3NpbmdfcnVsZXMjYmVhY29uX2hpbnRz">no IR<i class="fa fa-external-link-alt"></i></span>"이란 단서가 붙어있다는 것입니다. 이 플래그가 붙어있으면 해당 채널에서 AP나 ad-hoc 모드로 작동시킬 수 없습니다.<sup class="footnote-ref"><a href="#fn6" id="fnref6">[6]</a></sup> 그리고 사용자들의 제보를 종합해봤을 때 아마 현재로선 6GHz 대역을 활성화한 모든 국가에 대해 no IR 플래그가 붙어있을 가능성이 높습니다. 그러면 특정 국가를 통한 우회도 불가능하죠.</p>
<p>5GHz AP를 켜는 <span class="exturl" data-url="aHR0cHM6Ly90aWxkZWFycm93Lm9yZy8/cD1wb3N0Jm1vbnRoPTcmeWVhcj0yMDIyJml0ZW09bGFy">꼼수<i class="fa fa-external-link-alt"></i></span>에선 AP scan을 강제로 수행해 국가 감지가 정상적으로 이루어지도록 하는 방법을 썼는데, 6GHz AP를 켜기 위해선 펌웨어 내장 regdb 적용 자체를 막아야 하는 상황이고 이건 지금으로선 방법이 없습니다.</p>
<p>윈도우 11<sup class="footnote-ref"><a href="#fn7" id="fnref7">[7]</a></sup>에서도 6GHz 핫스팟은 안 되네요. 6GHz 대역 옵션 자체가 없습니다.</p>
<p><img src="001-ax210-hotspot.png" alt="AX210 핫스팟"></p>
<p>이에 대해 <span class="exturl" data-url="aHR0cHM6Ly9hbnN3ZXJzLm1pY3Jvc29mdC5jb20va28ta3Ivd2luZG93cy9mb3J1bS9hbGwvd2ktZmktNmUtNmdoei1ob3RzcG90LSVFQyVBNyU4MCVFQyU5QiU5MC81YTkzNmY2Zi1jOGY4LTQ3NzctOTA0ZS00NzQ2MTg0ZTQ3MGE=">마이크로소프트<i class="fa fa-external-link-alt"></i></span> 측에선 윈도우 문제는 아니라고 하고, <span class="exturl" data-url="aHR0cHM6Ly9jb21tdW5pdHkuaW50ZWwuY29tL3Q1L1dpcmVsZXNzL0ludGVsLUFYMjEwLWNhbi10LWNyZWF0ZS02R0h6LWhvdHNwb3QvbS1wLzEyMzg3NDUjTTMyNjcz">인텔<i class="fa fa-external-link-alt"></i></span> 측에선 규제 문제로 막아놨다고 합니다.</p>
<h2 id="MT7922">MT7922<a class="header-anchor" href="#MT7922"></a></h2>
<p>MT7922도 윈도우 11<sup class="footnote-ref"><a href="#fn8" id="fnref8">[8]</a></sup>에서 6GHz 핫스팟이 안 되네요. <span class="exturl" data-url="aHR0cHM6Ly9hbnN3ZXJzLm1pY3Jvc29mdC5jb20vZW4tdXMvd2luZG93cy9mb3J1bS9hbGwvcG9zc2libGUtdG8tZm9yY2UtNmUtaG90c3BvdC1pbi13aW5kb3dzLTExLzVhODA5ZmZjLWNhYzQtNDQxNC04YTUzLWQ2OTFhMzhkODE3NQ==">RZ608<i class="fa fa-external-link-alt"></i></span>에서 비슷한 보고가 있는 걸 보면 저만 안 되는 건 아닌가 봅니다.</p>
<p>대신 OpenWrt에서 시도해서 성공했습니다.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">root@OpenWrt:/# iwinfo</span><br><span class="line">phy0-ap0 ESSID: "wlan-6g"</span><br><span class="line"> Access Point: XX:XX:XX:XX:XX:XX</span><br><span class="line"> Mode: Master Channel: 85 (6.375 GHz) HT Mode: HE160</span><br><span class="line"> Center Channel 1: 79 2: unknown</span><br><span class="line"> Tx-Power: 3 dBm Link Quality: 62/70</span><br><span class="line"> Signal: -48 dBm Noise: unknown</span><br><span class="line"> Bit Rate: 2401.9 MBit/s</span><br><span class="line"> Encryption: WPA3 SAE (CCMP)</span><br><span class="line"> Type: nl80211 HW Mode(s): 802.11ac/ax/b/g/n</span><br><span class="line"> Hardware: 14C3:0616 105B:E0CB [Generic MAC80211]</span><br><span class="line"> TX power offset: unknown</span><br><span class="line"> Frequency offset: unknown</span><br><span class="line"> Supports VAPs: no PHY name: phy0</span><br></pre></td></tr></table></figure>
<p>txpower가 3dBm으로 찍히는데 이건 왜인지 모르겠네요. 하드웨어 결함이거나 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL29wZW53cnQvbXQ3Ni9pc3N1ZXMvNjg5">드라이버 탓<i class="fa fa-external-link-alt"></i></span>이거나 할 것 같은데, 작동에 문제는 없어서 일단 무시하고 넘어가겠습니다.</p>
<p>6GHz AP를 켤 때 몇 가지 주의사항이 있습니다. 이것도 다른 사람들이 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL21vcnJvd25yL1VTQi1XaUZpL2lzc3Vlcy84NyNpc3N1ZWNvbW1lbnQtMTMyMDk1MjA0NQ==">이미<i class="fa fa-external-link-alt"></i></span> <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL21vcnJvd25yL1VTQi1XaUZpL2lzc3Vlcy8xMDMjaXNzdWVjb21tZW50LTEzMjA5NjAzOTQ=">다<i class="fa fa-external-link-alt"></i></span> <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2dlZXJsaW5nZ3V5L3Jhc3BiZXJyeS1waS1wY2llLWRldmljZXMvaXNzdWVzLzEyMCNpc3N1ZWNvbW1lbnQtMTMwOTc1Njg0MA==">알아낸<i class="fa fa-external-link-alt"></i></span> 건데 저는 혼자 삽질을 한참 하고서야 깨달았네요…</p>
<ol>
<li>당연하지만 (6GHz 사용이 허용된 국가로) country를 설정해줘야 합니다.<br>
미설정시 6GHz 대역을 사용할 수 없습니다.</li>
<li>주 채널로 <span class="exturl" data-url="aHR0cHM6Ly93d3cuZXh0cmVtZW5ldHdvcmtzLmNvbS9leHRyZW1lLW5ldHdvcmtzLWJsb2cvdGhlLXJvYWQtdG8tYXAtZGlzY292ZXJ5LWluLTYtZ2h6Lw==">PSC(Preferred Scanning Channel)<i class="fa fa-external-link-alt"></i></span>를 사용해야 합니다.<br>
PSC의 전체 목록은 5, 21, 37, 53, 69, 85, 101, 117, 133, 149, 165, 181, 197, 213, 229 채널로 총 15개입니다.<br>
AP에서 non-PSC를 주 채널로 삼으면 STA에서 AP를 찾지 못할 수 있습니다. STA가 정말 PSC만 탐색할 수 있는 건지, 아니면 시간만 충분히 들이면 non-PSC도 탐색 가능한 건진 조사가 부족하여 잘 모르겠네요. 일단 표준에서는 6GHz 전용 AP는 PSC를 써야한다고 명시해 두었습니다.<sup class="footnote-ref"><a href="#fn9" id="fnref9">[9]</a></sup></li>
<li>암호화 방식으로 OWE(Enhanced Open), SAE(WPA3-Personal), WPA3-Enterprise를 사용해야 합니다.<br>
표준에서 6GHz에서 사용 가능한 암호화 방식에 제약을 걸어두었습니다.<sup class="footnote-ref"><a href="#fn10" id="fnref10">[10]</a></sup> WPA2-PSK나 암호화 미사용 등을 선택하면 hostapd에서 오류메시지를 띄우며 작동에 실패합니다.</li>
<li>SSID를 숨기지 않는 게 좋습니다.<br>
hidden 옵션을 켜면 STA에서 AP에 접속하지 못합니다. 아마 <span class="exturl" data-url="aHR0cHM6Ly9jb21tdW5pdHkuaW50ZWwuY29tL3Q1L1dpcmVsZXNzL0ludGVsLVItV2ktRmktNkUtQVgyMTAtMTYwTUh6LW5vdC1jb25uZWN0LXRvLXdpZmktNkUtNi1HSHovbS1wLzE0MTA2NTgvaGlnaGxpZ2h0L3RydWUjTTQyOTQ1">AX210의 no IR 플래그와 연관된 문제<i class="fa fa-external-link-alt"></i></span>인 것 같은데, <s>다른 무선랜카드에선 이런 문제가 없는지는 확인하지 못했습니다.</s> MT7922로는 hidden AP에도 접속됩니다.</li>
</ol>
<p>OpenWrt snapshot에서 MT7922/AP AX210/STA 조합으로 6GHz 대역 네트워크를 세팅하는 과정은 다음과 같습니다.</p>
<ol>
<li>
<p>무선랜카드 드라이버와 펌웨어 설치</p>
<ol>
<li>
<p>AX210: <code>opkg install kmod-iwlwifi iwlwifi-firmware-ax210</code></p>
</li>
<li>
<p>MT7922: <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL29wZW53cnQvb3BlbndydC9wdWxsLzEwNTY0">펌웨어 패키지<i class="fa fa-external-link-alt"></i></span>가 생기기 전까진 따로 다운로드 해줘야 합니다.</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">opkg install kmod-mt7921e</span><br><span class="line"><span class="built_in">cd</span> /lib/firmware/mediatek</span><br><span class="line">wget https://github.com/openwrt/mt76/raw/master/firmware/WIFI_MT7922_patch_mcu_1_1_hdr.bin</span><br><span class="line">wget https://github.com/openwrt/mt76/raw/master/firmware/WIFI_RAM_CODE_MT7922_1.bin</span><br></pre></td></tr></table></figure>
</li>
</ol>
</li>
<li>
<p><code>wpad-openssl</code> 패키지 설치 후 재부팅</p>
</li>
<li>
<p>uci 설정<br>
아래는 예시일 뿐입니다. <code>/etc/config/network</code>도 적절히 설정해주어야겠죠.</p>
<figure class="highlight txt"><figcaption><span>/etc/config/wireless (AP)</span></figcaption><table><tr><td class="code"><pre><span class="line">config wifi-device 'radio0'</span><br><span class="line"> option type 'mac80211'</span><br><span class="line"> option path 'pci0000:00/0000:00:1c.0/0000:01:00.0'</span><br><span class="line"> option channel '85'</span><br><span class="line"> option band '6g'</span><br><span class="line"> option htmode 'HE160'</span><br><span class="line"> option country 'KR'</span><br><span class="line"> option txpower '14'</span><br><span class="line"></span><br><span class="line">config wifi-iface 'default_radio0'</span><br><span class="line"> option device 'radio0'</span><br><span class="line"> option network 'lan'</span><br><span class="line"> option mode 'ap'</span><br><span class="line"> option ssid 'wlan-6g'</span><br><span class="line"> option encryption 'sae'</span><br><span class="line"> option key 'password'</span><br></pre></td></tr></table></figure>
<figure class="highlight txt"><figcaption><span>/etc/config/wireless (STA)</span></figcaption><table><tr><td class="code"><pre><span class="line">config wifi-device 'radio0'</span><br><span class="line"> option type 'mac80211'</span><br><span class="line"> option path 'pci0000:00/0000:00:1c.1/0000:02:00.0'</span><br><span class="line"> option htmode 'HE160'</span><br><span class="line"> option country 'KR'</span><br><span class="line"> option txpower '14'</span><br><span class="line"></span><br><span class="line">config wifi-iface 'default_radio0'</span><br><span class="line"> option device 'radio0'</span><br><span class="line"> option network 'wan'</span><br><span class="line"> option mode 'sta'</span><br><span class="line"> option ssid 'wlan-6g'</span><br><span class="line"> option encryption 'sae'</span><br><span class="line"> option key 'password'</span><br></pre></td></tr></table></figure>
</li>
<li>
<p><code>service network restart</code></p>
</li>
</ol>
<p>AX210만 그런진 모르겠는데 6GHz AP를 찾고 접속하는 데 느리면 몇 분씩 걸리기도 합니다. <code>iw dev phy0-sta0 scan | grep SSID:</code>로 AP scan을 수행해주면 접속이 빨라질지도요.</p>
<p>아치 리눅스나 윈도우 11에서도 이렇게 만든 6GHz AP에 잘 붙는 걸 확인했습니다.</p>
<p>그래서 중요한 속도는? 그럭저럭 나옵니다.</p>
<table>
<thead>
<tr>
<th>Wi-Fi 채널폭</th>
<th style="text-align:right">20 MHz</th>
<th style="text-align:right">80 MHz</th>
<th style="text-align:right">160 MHz</th>
</tr>
</thead>
<tbody>
<tr>
<td>최고 링크 속도 (2SS 기준)</td>
<td style="text-align:right">287 Mbps</td>
<td style="text-align:right">1.20 Gbps</td>
<td style="text-align:right">2.40 Gbps</td>
</tr>
<tr>
<td>iperf 속도</td>
<td style="text-align:right">(UL) 225 Mbps</td>
<td style="text-align:right">(UL) 912 Mbps</td>
<td style="text-align:right">(DL) 1.23 Gbps</td>
</tr>
</tbody>
</table>
<p>물론 안테나 간 거리와 각도를 최적화해서 얻은 결과이고, 실사용 세팅에선 이만큼 안 나옵니다.<br>
160MHz 채널폭에서 생각보다 속도가 안 나오는 게 아쉽네요. 컴퓨터가 느린 걸까요.</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">root@OpenWrt:/# iw dev phy0-sta0 link</span><br><span class="line">Connected to xx:xx:xx:xx:xx:xx (on phy0-sta0)</span><br><span class="line"> SSID: wlan-6g</span><br><span class="line"> freq: 6375</span><br><span class="line"> RX: 2767077980 bytes (5019078 packets)</span><br><span class="line"> TX: 2176796464 bytes (205189 packets)</span><br><span class="line"> signal: -30 dBm</span><br><span class="line"> rx bitrate: 2401.9 MBit/s 160MHz HE-MCS 11 HE-NSS 2 HE-GI 0 HE-DCM 0</span><br><span class="line"> tx bitrate: 1200.9 MBit/s 80MHz HE-MCS 11 HE-NSS 2 HE-GI 0 HE-DCM 0</span><br><span class="line"></span><br><span class="line"> bss flags: short-slot-time</span><br><span class="line"> dtim period: 2</span><br><span class="line"> beacon int: 100</span><br></pre></td></tr></table></figure>
<p>160MHz 채널폭 세팅을 했는데도 실제론 MT7922 → AX210에서만 160MHz를 쓰고 AX210 → MT7922에선 80MHz밖에 안 쓰는 것 같습니다. 이것도 왜인지 모르겠네요. 5GHz VHT160 세팅에선 속도가 기대한 대로 나오는 걸 봐선 HE160 지원 문제인 것 같기도 하고요.</p>
<p>그 외에도 MT7922에 자잘하게 아쉬운 점이 좀 있네요. 드라이버와 펌웨어 개발이 더 진척되면 나아지겠죠.</p>
<h2 id="사족">사족<a class="header-anchor" href="#사족"></a></h2>
<p>1️⃣ 아시다시피 이미 몇 년 전부터 <span class="exturl" data-url="aHR0cHM6Ly93d3cubXNpdC5nby5rci9iYnMvdmlldy5kbz9zQ29kZT11c2VyJm1JZD0xMTMmbVBpZD0xMTImYmJzU2VxTm89OTQmbnR0U2VxTm89MzE0MDcxNQ==">국내 법규<i class="fa fa-external-link-alt"></i></span>상 Wi-Fi 6GHz 대역이 허용되었습니다.<br>
국내 전파규제는 2.4/5 GHz에서 최대 복사전력(EIRP)을 고정하는 방식을 택했고, 이 방식에선 대역폭(BW)이 넓어질수록 전력밀도(PSD)가 떨어집니다. (<code>EIRP = 10*log(BW) + PSD + G</code>인데 여기서 안테나 이득 G는 잠시 무시하겠습니다.)</p>
<table>
<thead>
<tr>
<th>대역폭</th>
<th style="text-align:right">20 MHz</th>
<th style="text-align:right">40 MHz</th>
<th style="text-align:right">80 MHz</th>
<th style="text-align:right">160 MHz</th>
</tr>
</thead>
<tbody>
<tr>
<td>전력밀도</td>
<td style="text-align:right">10 dBm/MHz</td>
<td style="text-align:right">7 dBm/MHz</td>
<td style="text-align:right">4 dBm/MHz</td>
<td style="text-align:right">1 dBm/MHz</td>
</tr>
<tr>
<td>복사전력 (동일)</td>
<td style="text-align:right">23 dBm</td>
<td style="text-align:right">23 dBm</td>
<td style="text-align:right">23 dBm</td>
<td style="text-align:right">23 dBm</td>
</tr>
</tbody>
</table>
<p>이와 달리 (실내용) 6GHz에서는 <span class="exturl" data-url="aHR0cHM6Ly93d3cubWlzdC5jb20vcG93ZXItc3BlY3RyYWwtZGVuc2l0eS8=">최대 PSD를 고정<i class="fa fa-external-link-alt"></i></span>하는 방식을 택했는데, 이 방식에선 대역폭이 넓어지는 만큼 EIRP도 올라가므로 SNR 면에서 손해가 없습니다.</p>
<table>
<thead>
<tr>
<th>대역폭</th>