크래커가 PC 제어를 목적으로 만든 프로그램이 내 PC에 설치되어서 내 의지와는 상관없이 광고를 클릭하던지 이상한 곳으로 메일을 보내는 등의 일을 한다는 군요. 뭐 개인 정보를 빼내가는 건 당연한 것이고 그 외의 작업들은 옵션인 듯 합니다.

 외국의 어떤 해커가 해군 시스템에 프로그램을 심어서 광고를 클릭하게 했다던데... 참 대단한 생각을 했더군요. 점검도 잘 안하고 허술하다는 것을 알고 한 것일까요? 한대만 뚫리면 근처에 비슷한 IP를 사용하고 있는 PC가 감염되는 것은 일도 아니겠습니다만은... 그래도 해군 시스템인데.... ㅡ_ㅡa...

 PC가 삶에 깊숙히 파고들어서 PC를 켜놓는 시간이 늘어나게 됬는데, 이런 점을 악용하는 군요. 안티 바이러스 프로그램은 필수가 된지 오래고, 이제는 전문 안티 봇 프로그램을 따로 깔아야 하는 것은 아닌지 걱정이됩니다. ㅜ_ㅜ...

 프로세스를 주기적으로 모니터링 해야겠네요. (프로그램을 또 하나 만들어야 하는 것인가.. ㅜ_ㅜ)


예전에 개발하면서 적어놓았던 것인데, 블로그가 이전되서 다시 옮겨왔습니다. ^^

< 2004 05 11 GUI ( Graphic User Interface) >


으옷... @0@/~ 드뎌 네모난 커서에서 벗어났습니다 ㅋㅋㅋ 이틀동안 삽질한 끝에

Icon 파일을 읽어 낼 수가 있게 되었네요.. 화면 중앙에 보시면 콘솔위에 삼각형의

하늘색 커서가 있음을 알 수 있습니다. 요 아래쪽의 스샷을 보시면 파란색 네모가

동동~ 떠있는데, 고게 Icon 파일의 힘으로 삼각형으로.. ㅡ0ㅠ.. 감동..



< 2004 05 08 GUI ( Graphic User Interface) >

윈도우의 폰트가 기존의 래스터에서 돋움체로 바뀌어서 한컷 찍어 올립니다. 양쪽에

는 뽀대를 살리기위한 비트맵 로더가 떠있구요, 가운데 보시면 돋움으로 무장한

GUI Shell이 오랜지색 커서와 함께 두둥 떠 있는 걸 보실 수 있습니다.

으흣.. 폰트가 바뀌니 훨씬 나아 보이는군요.. ㅋㅋㅋ

앗쌀~ 홧팅 @0@/~



< 2004 05 06 GUI ( Graphic User Interface) >


아아.. 오래간만에 한컷 올립니다. 에궁에궁 출장이다 머다 해서 한동안 손을 조금

놓고있었기때문에, 헐헐헐..

이번에 스샷의 관전 포인트(??)는 제 마스코트랑 열혈강호가 올라가있는 BMP Viewer

가 아니라, 요것들이 모두 Application, 즉 User Level의 프로그램들이라는 것에 초점

을 맞추어야 한다고.. 쿠.. 쿨럭..;;;;

그리고 GUI Console에 오랜지색 네모 커서도 넣었고, 윈도우 테두리도 녹색에서

오랜지 빛으로 바꾸었습니다. 이게 더 보기가 좋군요.. ㅋㅋㅋ

일단 곧 커널이랑 하드 이미지도 릴리즈를.. 글고.. 곧 소스도..

쿠.. 쿨럭..;;; 정리는 안하고 지저분하게 삽질만 계속 하고 있는..

까.. 마.. 구.. @0@/~




< 2004 04 11 GUI ( Graphic User Interface) >


위에서 보시는 스샷은 아래의 4월 3일자의 스샷과 별 차이가 없는데요, 사실 비슷하긴

한데, 내부적으로는 상당한 변화가 있었기때문에 기념으로 한컷 올립니다.

으읏 진짜 이번엔 문제가 너무 심각해서 며칠째 고심해서 고쳤는지 ㅡ0ㅠ...

이번에 수정하면서 그런생각이 들더군요.. 과연 이 삽질의 끝에는 머가 있을까..

굉장히 궁금합니다 그려.. ㅋㅋㅋㅋ

4월 3일자에서 있었던 키의 문제는 해결한 스샷입니다. 사실 외관은 똑같군요..

( 아아.. 암것도 안한거 같오.. ㅡ0ㅠ... 억울..크윽.. )





< 2004 04 03 GUI ( Graphic User Interface) >



이번에 구현된 GUI system call을 테스트 하기 위해 만든 Application입니다.

기본적으로 하는일은, CUI에서 보여지는 80 * 25의 Text 화면을 그대로 옮겨서 보여

주는 것이지요.

아직 Key 문제가 확실히 해결되지 않아서 약간 문제가 있지만 그런대로

볼만은 하군요.. ㅋㅋㅋㅋ


< 2004 03 23 ETC ( ^ㅠ^ ) >



제가 목표로 하고 있는 GUI의 모습입니다.

Evil WM 이라고 굉장히 가볍다고 하는군요. 저는 윈도우를 쓰기때문에 잘 모름..

그러나 딱 봤을때 이미 필이 왔죠.. 보면 볼수록 멋집니다.

@0@/~~





< 2004 03 27 CUI ( Console User Interface) >




첫번째 화면은 이번에 릴리즈된 커널을 Bochs에서 돌린 화면입니다.

showdevice 했을때, com1, HDD, RamDisk 순으로 보이는 군요.

기본적으로 다 Mount된 상태로 실행되게 했습니다.

이게 테스트 하긴 더 편하더라구요..

두번째 화면은 KKAMAGUI Editor를 돌린 화면입니다. 간단한 텍스트를 입력하고,

/a.txt로 저장했어요.

세번째 화면은 KKAMAGUI Editor를 돌려 시리얼로 전송받은 소스코드를 읽은

화면이에요. 제가 짠건 아니지만 걍 있길래 전송해서 열어봤죠.. >_<



< 2004 03 24 CUI ( Console User Interface) >


이번에 릴리즈된 커널을 Bochs에서 돌린 화면입니다. showdevice 했을때,

램 디스크 하나랑 시리얼 포트, 그리고 추가된 하드가 보이는군요.

아참 램 디스크( rd0 )는 이번 커널에는 아니고.. 곧 릴리즈될 커널에 있는 건데..

Screen shot이 잘못됬네요.. 여튼 '/'에 Mount 한다음 내용물을 보여준겁니다.

므흣.. 좋네요~ ^0^/~


< 2004 03 23 ETC ( ^ㅠ^ ) >


제가 주로 쓰는 kkamagui를 그려봤습니다. 아마 지난 설인걸로 기억하는데요..

ㅋㅋㅋ 그때 별로 할일이 없어서 그림판으로 그렸던듯 하군요

그냥 한번 웃어보시라구요 ^0^/~



< 2004 03 15 CUI ( Console User Interface) >



CUI Screen shot 입니다. 맨 위에 화면은 처음 부팅했을때 보이는 화면입니다.

오늘 페이지를 추가하면서 생긴 화면이네요.. ^^

두번째 화면은 Worms라고 제가 공유메모리를 구현하고 그걸 테스트하기위해 만든

프로그램입니다. 처음에 녹색 한마리가 이리저리 돌아다니는데요, 이게 일정시간

지나면 상태도 변하고 그에 따라 먹이도 먹고 분열도 하고 싸움도 하는 그런 프로그램

입니다. 머 알고리즘이 그리 복잡하지 않기 때문에 크게 변화는 없구요.

주기적으로 늘었다 줄었다 하는군요. 심심하신 분은 한번 실행해 보심이.. ㅋㅋ


< 2004 03 14 CUI ( Console User Interface) >


CUI Screen shot 입니다. 맨 위에 화면을 보시면 Device 목록에 hda0 및 hdc0 두개의

하드디스크와 시리얼 포트 2개가 있음을 알 수 있습니다.

mount 명령으로 /에 hdc0를 mount하고 ls를 통해 파일을 조회한 화면입니다.

두번째 화면은 B2OS를 만드신 분이 CUI버전으로 테트리스를 제작하셨는데요, 그걸

그대로 포팅해서 제 OS에 돌린 화면입니다. ^^

B2OS 주인장님께 거듭 감사를 드립니다. (_ _)


< 2004 03 14 BoxBox Prototype>

GUI Prototype Screen shot 입니다. 이름은 BoxBox이구요. 사각형으로 이루어진

간단한 GUI를 목표로 하고 있기 때문에 이름을 이렇게 지었습니다.

커서( 가운데의 하얀 사각형 )의 모양까지 현재는 사각형을 띄고 있는데요,

조만간 커서는 삼각형으로 만들어볼까 생각중입니다. ㅋㅋ

윈도우는 evilwm에 영향을 받아서 녹색의 1 pixel로 이루어져 있구요, 내부는

녹색을 약간띄는 어두운 색으로 맞추어놨습니다.

테스트를 위해 여러 윈도우를 겹쳐놨는데, 생각난김에 한컷 잡아서 올립니다.

볼수록 모노크롬 모니터 시절을 생각나게 하는군요. ^^

개인적으로는 아주 맘에 드는데 말이죠. ㅋㅋ

이런 멋진 GUI를 만들게 해주신 Linefeed 님과 Ed 님께 감사를.. ㅎㅎ


 틈틈히 만든 닌텐도 DS(이하 NDS)용 한글 입력기와 간단한 메모장 프로그램을 공개합니다. 생각보다 일이 많아서 릴리즈가 조금 늦어졌습니다. NDS용 홈브루(Homebrew)는 많이 있습니다만, 한글 입력이 가능한 홈브루가 없어서 만들어야겠다고 생각만하다가 이제서야 만들었네요. ^^;;;

 프로그램은 아래와 같이 최상단의 페이지 번호와 그 아래의 메모입력 화면, 마지막으로 한글/영문/숫자 키보드로 이루어져있습니다. NDS의 듀얼 스크린의 장점이 여기서 나오더군요. ^^
사용자 삽입 이미지

사용자 삽입 이미지 사용자 삽입 이미지

 이 프로그램이 제공하는 기능은 아래와 같습니다.
1. 완성형 한글/영문/숫자 입력 기능 : 완성형 한글 오토마타를 이용하여 한글 조합 및 출력 가능. 실제 키보드와 거의 동일하게 자판을 배열하고 구성함. Shift 키와 Delete 키를 지원하고 Space바 좌측의 모드 변환 키를 통해서 키보드의 타입 변경 가능.
2. 메모 입력 기능 : 1줄당 최대 영문 42자 or 한글 21자 입력 가능. 최대 10줄까지 입력가능.
3. 메모 페이지 이동 기능 : 메모 페이지를 최대 20장까지 지원. 키보드 상단의 "<<" or ">>" 버튼으로 메모 페이지 이동가능. 최상단에 현재 페이지 번호 표시.
4. 메모 내용 저장 기능 : 페이지 이동 시 or ""저장" 버튼 클릭 시 메모를 저장하는 기능. NDS 재시작 후에도 이전 메모 기록 확인 가능

 프로그램의 기능은 굉장히 간단한데, 글로 쓸려니 길어집니다. ^^ 한번 써보시면 더 쉽게 이해하실 수 있을 겁니다. 아래는 실제 사용하는 동영상입니다.



그럼 좋은하루 되시길~ ^ㅡ^)/~
ps) 아래는 실행파일입니다.


 약 이틀간의 작업끝에 한글 오토마타의 수정을 끝내고 아래와 같은 메모장 프로토타입을 만들었습니다. 이제 상단에 기능 버튼(오늘 일자 표시 및 삭제 기능)만 추가하면 릴리즈해도 괜찮겠군요. 시연 동영상이라도 하나 찍어서 올려야겠습니다. 물론 실행파일도 같이요 ^^)/~
사용자 삽입 이미지

메모장 프로토 타입




 제가 만든 홈브루가 굉장히 많은데, 이번 것 만큼 손이 많이가는 것도 처음인것 같네요. 여튼 진행상태로 보면 오늘 내일 안에 메모장 프로토타입을 완성할 수 있을 것 같습니다. 파일로 저장하고 여러 메모를 관리할 수 있도록 하면 간단한 Todo List 메모용으로 사용해도 되겠네요 ^^;;;

 여유가 좀 된다면 메모 검색화면이나 기타 기능도 넣으면 좋겠는데, 일단 고민을 좀 해봐야겠습니다. 일단은 1차 릴리즈에서 버그가 없는 것이 더 중요하니까요 ^^)/~~


 아이팟 터치(iPod Touch)의 한글 지원 소식에 감명받아서 새벽에 잠깐 짬을내서 Nintendo DS( NDS )용 한글 입력기를 만들어봤습니다. ^^;;; 아직은 테스트 상태라서 많이 불안정한데, 일단 동작은 하니까 스크린 샷을 올려봅니다. ^^

사용자 삽입 이미지

한글 입력 테스트


 

 아이팟 터치의 키보드가 너무 예뻐서 그대로 올려봤는데, NDS에 올리니 약간 포스가 떨어지는군요. ^^;;;
 
 오늘 테스트 덕분에 한글 출력에 한가지 문제를 발견했습니다. 제가 NDS에 올린 폰트는 완성형이었는데, 윈도우에서는 확장 완성형 폰트를 사용했습니다. @0@)/!!! 왠지 '틍'과 같은 단어를 입력할때 깨어진다 싶었더니... 확장 완성형에서 지원하는 문자라서 그랬습니다.

 확장 완성형 폰트를 만들어 넣는 것은 큰 문제가 안되지만.... 폰트 데이터가 너무 커지면 용량의 한계때문에 문제가 발생할 소지가 있어서 상당히 조심스럽습니다. 이 문제는 좀더 고민해본 다음 결정해야겠습니다. ^^;;;

 벌써 해가뜨네요... ㅜ_ㅜ... 오늘도 일찍 일어나기는 힘들 것 같습니다. ㅜ_ㅜ...
 
=== 2007/11/26 추가 ===

 너무 많은 분들이 이 글을 보러 오셔서, 오늘까지 진행상황을 더 추가했습니다. ^^ 폰트를 더 추가할까 하다가 NDS의 용량이 그리 크지 않아서 포기하고 한글을 조합하는 오토마타를 조금 손봐서 2360자용 한글 입력기를 만들었습니다.

 현재 한글/영어 대소문자/숫자 및 특수문자 모두 입력 가능하며 특수문자는 자판 숫자 및 배열 때문에 빠진 것이 좀 있습니다. 추후 작업을 조금 더 진행하여 특수문자를 다 추가해야 할 예정입니다. (혹시 아이팟 가지고 계신분 있으시면 특수문자쪽 키보드 자판 배열 좀 알려주세요 ^^;;;)

 완성형 한글 입력 및 영어, 숫자 입력을 캡쳐한 화면입니다. 다음에 작업이 완료되면 새글을 통해 릴리즈하겠습니다. ^^
사용자 삽입 이미지

영어 대문자 입력

사용자 삽입 이미지

영어 소문자 입력



사용자 삽입 이미지

한글 입력

사용자 삽입 이미지

한글 및 숫자/특수문자 입력


 ps) 작업을 하다보니 어느새 날이 밝아오는군요. ㅜ_ㅜ...


=== 2007/12/01 추가 ===

 프로토타입 개발을 완료했습니다. ^^ 자세한 내용은 http://kkamagui.tistory.com/238 에서 확인하실 수 있습니다. 동영상과 프로그램을 포함하고 있습니다. ^^
 애플 iPod 터치용 한글 입력기가 나왔답니다. ^ㅡ^)/~!! 일반 유저인 서성진씨(http://coryas.com/ipod)가 만들었다니 대단하군요. 아래는 시연 동영상입니다. ^^

 
 저도 NDS에 비슷한 방식의 한글 입력기를 생각하고 있었는데, 오토마타쪽에 약해서 도중에 포기했습니다. 이 동영상을 보니 왠지 저도 하나 해야할듯한 기분이 드는군요. 오늘부터 한글입력기 제작에 들어가야겠습니다. ^^

 같은 한국인으로써 왠지 뿌듯하네요 ^^)/~
 아는 후배에게 방금 들었습니다. POC 2007 세미나에서 NDS를 이용한 해킹을 주제로 "Hacking with Nintendo DS" 를 발표하셨던 i3eat 님께서 제 사이트를 참고하셨다더군요. 세미나에 참석했던 후배가 물어봤는데 그렇게 말씀하셨답니다.

 POC 2007에 직접 가지 못해서 자세한 내용은 알지 못하지만, 왠지 큰 세미나에 제가 한몫 한 것 같아서 기분이 좋군요.(사실 많이 뿌듯하다는 ^ㅡ^). 나중에 기회가되면 POC 2007 세미나 자료를 봐야겠군요.

 NDS 홈브루(Homebrew) 개발에 대한 내용은 http://kkamagui.tistory.com/category/NDS%20홈브루(Homebrew)에서 보실 수 있습니다. ^^

 나중에 i3eat 님을 만나게되면 인사라도 드려야겠습니다. ^^  
 왠지 오늘은 잠이 잘 올것 같네요~ 다들 좋은밤 되시길~ ^^
 운동을 갔다 오니 벌써 세미나가 시작되서 후다닥 들어갔더니 한 20분치를 날려먹었습니다.ㅜ_ㅜ 세미나 내용은 SE Linux를 이용해서 좀더 보안에 강한 구조로 만드는 것인데, 일단 ARM 기반의 임베디드 리눅스라는 점과 커널과 파일 시스템을 직접 손봐야 한다는 점에서 난이도가 좀 있었지요. ^^;;;

 아무 생각없이 세미나 자료를 죽 훓어보고 있었는데, 오~!!! 나름대로 준비를 좀 했습니다. 솔찍히 말하자면 스택과 힙 오버플로우를 이용한 쉘 획득은 거의 막은 듯 보였습니다. 물론 제가 리눅스를 잘 모르기때문에 다른 방법이 있는지는 잘 모르겠지만, 커널쪽의 API를 수정해서 프로세스 실행 쪽을 모니터링하고 있더군요.

 자세한 로직은 공개하기가 힘들지만 딱 보기에도 이렇게 하면 마음대로 실행이 안되겠구나 하는 생각이 들었습니다. 커널을 수정하고 테스트하는 것이 쉬운 방법이 아닐텐데 용케 했더군요.

 파일 시스템도 JFFS2를 수정해서 파일별로 권한 정보 및 인증 정보를 따로 남기도록 해놨습니다. 따라서 커널이 프로그램을 실행할 때 그 정보를 이용해서 실행파일이 변조되지 않은 유효한 것인지 그리고 실행할 수 있는 것인지를 처리하더군요. 그 외에도 많은 기능이 있는데 일일이 나열하면 왠지 안될 것 같아서 이만 줄입니다. ^^;;;

 제가 관심이 있는 분야가 이쪽이라서 그런지 아주 흥미진진하더라구요. 후배들 덕에 공부 한번 제대로 했습니다. 후배들 화이팅~!!! ^ㅡ^)/~
 티스토리에 글을 쓰다가 문득 위에 "동영상" 이라는 버튼이 보였습니다. 이게 뭘까? 한참을 고민하다가 설마하는 생각에 제가 가지고 있는 동영상을 올려보니 블로그에 표시되는 것이 아니겠습니까? @0@ 이글루스에서는 상상도 할 수 없던 것이 티스토리로 옮기니까 가능해 지는군요.

 생각난 김에 예전에 만들어 뒀던 닌텐도 DS( NDS )용 작은 커널(Kernel) 시연 동영상을 올립니다. ^^ 커널은 OS(Operating System)의 핵심적인 부분으로 주변기기 제어에 필요한 잡다한 코드들을 제외한 핵심이라고 보시면 되는데요, 어차피 닌텐도 DS( NDS )는 그렇게 주변기기가 많지 않고 마이크 말고는 다 지원하고 있으니 작은 OS라고 해도 괜찮을 것 같습니다.
 
 아래에서 시연 동영상을 보실 수 있습니다. 시작 화면이 시커멓게 나와서 조금 안타깝군요. ㅡ_ㅜ... 운영체제답게 멀티 태스킹을 지원하고 사운드 및 키패드를 이용해서 게임(??)을 Play 할 수 있습니다. 정겨운 버블버블 음악이 게임 내내 흘러나오고 @$를 다 먹으면 게임이 끝납니다. ^^;;;

 구현에 관한 자세한 내용은 제 티스토리의 http://kkamagui.tistory.com/40 에서 보실 수 있고 NDS 홈브루 개발에 대한 내용은 제 티스토리의 홈브루 개발 카테고리 http://kkamagui.tistory.com/category/NDS%20홈브루(Homebrew) 에서 보실 수 있습니다.

 그럼 화질은 좀 떨어지지만 즐겁게 감상하시길 바랍니다. ^^;;;;

 


원문 : http://www.thefengs.com/wuchang/work/courses/cs592_spring2007/ 
 
 지인의 블로그에서 오래전에 Cheating in On-line Games에 대한 링크와 자료들을 봤었는데, 나름 바쁜 일이 있어서 그냥 지나쳤습니다. 오늘 문득 생각이나서 다시 들어가보니 내용이 괜찮다는 덧글이 많이 붙어있더군요. 그래서 한번 읽어볼 겸 올려봅니다.

 온라인 게임용 보안 프로그램(nProtect, XTrap, 헥쉴드, 가드캣 등등)에 관심이 많으신 분들은 읽어보시면 방어 프로그램의 원리를 알 수 있을 겁니다. 창과 방패와 같다는 느낌이 드는군요.
 우수한 방패의 약점을 분석해서 더 우수한 창을 만들고 반대로 우수한 창의 약점을 분석해서 더 우수한 방패를 만들 수 있는 것처럼 해킹과 보안 역시 비슷한 관계가 있는 것이 아닌가 생각해봅니다. ^^;;;

 아래는 원문 사이트의 내용입니다.

Instructor:  

Wu-chang Feng (wuchang at cs dot pdx dot edu)
Office hours: After class
Office location: Fourth Avenue Building Suite 120-17(map)
Web site: http://www.thefengs.com/wuchang/work/courses/cs592
Course e-mail list: http://groups.yahoo.com/group/pdx-cs592
Course e-mail: pdx-cs592 at yahoogroups dot com

Location and Time:
SAB 209, Tuesdays and Thursdays, 2:00pm-3:30pm

Course content:  

  • Lecture 1 (4/3): Introduction (ppt | pdf)
  • Lecture 2 (4/5): On-line PC games and their cheats (ppt | pdf)
  • Lecture 3 (4/10): Software architecture of cheats (slides available through group)
  • Lecture 4 (4/12): Intel's AMT platform (ppt | pdf)
  • Optional class (Gligor lecture at UO) (4/17)
  • Lecture 5 (4/19): Rootkits Chapters 1-3 (ppt | pdf)
  • Lecture 6 (4/24): Rootkits Chapters 4 (ppt | pdf)
  • Lecture 7 (5/1): Rootkits Chapters 5-6 (ppt | pdf)
  • Lecture 8 (5/3): Rootkits Chapters 7-8 (ppt | pdf)
  • Cheat surveys (5/8): RTS | FPS | MMORPG
  • No class (5/10)
  • Lecture 9 (5/15): Rootkits Chapters 9-10 (ppt | pdf)
  • Lecture 10 (5/17): Anti-Debuggers (ppt | pdf)
  • Lecture 11 (5/22): Example Rootkit Rustock.B (paper link | ppt | pdf)
  • Lecture 12 (5/24): Reversing #1 (ppt | pdf | references)
  • Lecture 13 (5/29): Reversing #2 (ppt | pdf | Excerpts from suggested books)
  • Lecture 14 (5/31): System Integrity Services and Obfuscators - Slides:(ppt | pdf) Paper:pdf
  • Final presentations
    • MMO cheats - MMO Glider (Alex Ten): pdf
    • MMO cheats - MMO Glider (Dan Lake): pdf
    • RTS cheats - Genesis/Zerocraft (Wen Sun, Yang Chen): ppt
    • FPS cheats - HL2Hook (Sam Moffatt): odp | pdf

Grading:

  • Phase 2: Survey (Due 5/8) = 40%
  • Phase 3: Cheat disassembly and AMT counter-measure description (Due 6/12) = 60%

'Windows System Application' 카테고리의 다른 글

15 오디오 드라이버를 이용한 exploit 개발  (0) 2008.01.14
13 안티 크래킹 관련 자료  (4) 2007.12.08
01 PE 파일 분석-헤더분석  (2) 2007.11.16
04 System Monitor  (0) 2007.11.15
03 Network Monitor  (2) 2007.11.15

FAT 파일 시스템(File System)

원문 :  http://kkamagui.springnote.com/pages/345737


들어가기 전에...

1.FAT 파일 시스템 개요

 FAT 파일 시스템은 전통적으로 DOS 시절부터 사용되어 왔다. FAT 파일 시스템이 다른 파일 시스템과 구별되는 점은 파일 내용을 클러스터 단위로 구성하고 이것을 링크드 리스트(Linked List)의 형태로 보관하는 것이다.

 말로 하면 어려우므로, 일단 아래 그림을 보도록 하자.

FAT1.PNG

<FAT의 간략한 구조>



 위 그림과 같이 파일은 고정된 크기의 클러스터(Cluster) 단위로 나누어져 있으며, 그 클러스터들은 클러스터 풀(Cluster Pool)에 존재하는 클러스터를 연결한 클러스터 채인(Cluster Chain)으로 되어있다. 실제 FAT 파일 시스템에서 클러스터 풀은 FAT(File Allocation Table)이라는 용어를 사용한다.

 클러스터(Cluster)란 별개 아니고 여러개의 섹터를 모아서 하나의 블럭 단위로 보는 것이다. 윈도우 포맷 프로그램을 이용해서 포맷을 하면 일반적으로 클러스터의 크기를 4Kbyte로 잡는데, 이 말은 한 섹터(Sector)의 크기가 512byte 이므로 8개의 섹터를 하나의 블럭으로 설정한다고 보면 된다.

 그럼 왜 클러스터라는 말을 쓰는 것일까? 그것은 섹터를 블럭으로 관리하면 얻는 이득이 있기때문이다. 아까 잠시 클러스터 풀에 대한 이야기를 했는데, 고용량일수록 클러스터 풀(FAT 영역)이 커지게 된다. 이것이 커질수록 파일을 읽고 쓸때 관리해야 하는 양이 늘어나게되고, 또한 디스크의 비어있는 공간이 줄어들게 된다. 이것을 블럭으로 관리하게 되면 이런 문제가 해결되며, 또한 블럭 단위로 읽기 쓰기를 수행함으로 얻는 효율로 인해 성능이 좋아지게 되는 것이다.

 특히 요즘처럼 파일의 크기가 큰 상황에서는 클러스터의 크기가 큰 것이 성능 향상에 도움이 된다. 하지만 클러스터의 크기가 무조건 크다고 좋은 것은 아니다. 아까 이야기 했듯이 클러스터의 단위로 작업을 하기 때문에, 작은 파일 같은 경우는 클러스터 하나를 할당받아서 대부분의 영역을 낭비하는 경우도 있으니 적당히 조절해야 한다.


 자 그럼 FAT 파일 시스템의 큰 특징을 알아봤으니 세부적인 내용을 알아보자

 FAT 파일 시스템은 총 3가지의 타입이 있다.

  • FAT12 : 클러스터의 개수가 1 ~ 0xFFF 까지를 가지는 타입. 플로피 디스크에서 주로 사용됨
  • FAT16 : 클러스터의 개수가 0xFFF ~  0xFFFF 까지를 가지는 타입. 소용량에 주로 사용됨
  • FAT32 : 클러스터의 개수가 0xFFFF ~ 0xFFFFFFFF 까지를 가지는 타입. 대용량에 주로 사용됨

 세가지 타입 모두 내부 포맷은 비슷하며, 차이점은 클러스터 개수라고 볼 수 있다.(물론 그것만 차이나는 것은 아니다. ㅡ,.ㅡ;;; 오해하지 말자.). 클러스터의 개수에 따라 FAT 타입을 분류한다고 했는데, 이 클러스터 개수는 어떻게 구하는 것일까? 실제 데이터 영역을 구성하는 크기를 가지고 계산하는 것일까?


 실제 타입 구분에 사용되는 클러스터의 크기는 디스크 전체 크기를 범위로 한다. 즉 아래의 공식으로 클러스터의 크기를 구하고 그것으로 타입을 유추하는 것이다.

클러스터의 개수 = 파티션 또는 디스크의 크기 / 클러스터의 크기

 이렇게 구한 클러스터의 개수는 실제로 사용가능한 데이터 영역의 클러스터의 개수와 비교하면 당연히 큰값을 가진다. 왜냐하면 디스크 또는 파티션 영역에 데이터만 들어가는 것이 아니고 FAT 파일 시스템을 관리하기위한 파일 시스템 메타 데이터(Meta Data)를 포함하기 때문이다.

 이제 파티션과 메타 데이터에 대해서 알아보자.


2.파티션(Partition)

 파티션에 대해서 익히 알고있고 들어봤을 것이다. 디스크 전체를 하나로 사용하는 것이 아니라 그 안에 C: D:와 같이 영역을 분할하여 사용하는 것이 파티션이다. 파티션을 나누면 디스크를 효율적으로 관리할 수 있는 장점 때문에 약간의 디스크 공간을 낭비하더라도 파티션을 해서 많이 사용한다(아래와 같이 나눌 수도 있다).

Partition.PNG


 그럼 어떻게해서 파티션이 나누어지는 것일까? 파티션을 나누게 되면 그 파티션에 대한 정보가 MBR(Master Boot Record)란 영역에 삽입되게 된다. MBR이란 디스크의 첫번째 섹터로 부트 코드와 여러가지를 정보를 포함하고 있다. MBR의 존재는 맨 마지막 510째부터 0x55 0xAA가 있는지 확인하여 이것이 있으면 MBR이 존재한다고 보면 된다(사실 다 있다. ㅡ_ㅡ;;; OS를 깔아 쓰면 저것 말고도 여러 정보가 MBR에 들어가 있다.)

 MBR의 세부구조를 한번 알아보자.

MBR.PNG

 헥사 에디터 프로그램으로 4개의 파티션으로 나누어진 USB 메모리의 MBR을  캡쳐한 화면이다. 좌측 상단에 0xEB 0x3C 0x90의 3Byte가 있는데, 이부분은 부트 코드의 시작으로 jmp 하라는 어셈블리어 명령이다. 굳이 필요한 것은 아니나 윈도우에서 MBR 인식을 위해서는 이 부분이 꼭 필요하다( 이부분이 0x00으로 비어져있는 경우에 윈도우가 MBR로 인식하지 못하는 것을 발견했다).

 우측 하단에 0x55 0xAA의 매직넘버가 보이고 그위에 붉은 색 줄이 쳐져있는 16byte의 라인이 보인다. 이부분이 파티션 데이터의 시작으로 그 앞부분은 모두 Boot Code의 용도로 사용되거나 아니면 사용되지 않는다. 파티션 정보는 16Byte씩 4개로 총 64Byte로 되어있으며 각 항목은 아래와 같은 구조체로 되어있다.

  1. /**
        Partition에 대한 정보를 포함하는 구조체
    */
    typedef struct partitionStruct
    {
        BYTE bBootIndicator;
        BYTE bStartingHeader;
        WORD wStartingSectorAndCylinder;
        BYTE bSystemID;
        BYTE bEndingHeader;
        WORD wEndingSectorAndCylinder;
        DWORD dwRelativeSector;
        DWORD dwTotalSector;
    } PARTITION, * PPARTITION;

  여기서 중요하게 봐야할 부분은 위에서 파란색으로 표시된 부분인데, 그 외 부분들은 옛날 도스 시절에나 사용된 필드기 때문에 무시해도 된다. 각 필드는 아래와 같은 의미를 가진다.

  • Boot Indicator : 부팅 가능한 파티션이면 0x80을 가짐. 그렇지 않으면 0x00
  • System ID : 파일 시스템의 ID. 일반적으로 윈도우에서 사용하는 값은 0x0B. 그 외의 값도 많으나 잘 쓰이지 않음
  • Relative Sector : 파티션이 시작되는 섹터.
  • Total Sector : 총 파티션의 크기

  위 정도값만 제대로 설정하면 윈도우에서 정상적으로 파티션 된 것으로 인식한다. MBR에 파티션 필드는 총 4개가 있으므로 파티션은 최대 4개까지 만들 수 있다. 그럼 도스 시절에는 파티션이 4개 이상이 가능했는데, 이것은 어떻게 한 것일까? 옛날 도스에서는 확장 파티션(Extension Partition)이라는 기능을 사용했다. 즉 MBR 파티션에는 확장 파티션 영역을 표시해 놓고, 확장 파티션 영역의 첫번째 섹터로 이동하면 그 첫번째 섹터에 다시 파티션 정보 + 확장 파티션 정보를 기입하는 식으로 체인으로 연결했던 것이다(이렇게 하면 디스크 용량이 허락하는 한 거의 무한대의 파티션을 생성할 수 있다. ㅡ,.ㅡ;;;;). 도스 이후에는 별로 사용하지 않으므로 일단 넘어가자. 궁금한 사람은 http://www.nondot.org/sabre/os/articles에 가서 Partition 쪽을 보면 된다.



3.파일 시스템 메타 데이터(File System Meta Data)

 FAT_메타_데이터_구조.PNG

 FAT 파일 시스템을 구성하는 메타 데이터는 위와 같은 순서로 구성된다. 각 항목에 대한 설명은 아래와 같다.

  • PBR : 파티션 부트 레코드(Partition Boot Record)의 약자로서 파티션에 대한 전반적인 정보를 저장하고 있음. 핵심적인 부분
  • Reserved : 특수한 용도(Root Directory의 시작위치를 조절하거나 특수한 데이터를 저장할 용도)로 사용되는 공간. 존재하지 않을 수도 있음
  • FAT1/2 : 클러스터 풀로써 클러스터 체인을 구성하는 부분. 뒤에오는 Data Cluster의 개수에 따라 가변적인 크기를 가짐. FAT1은 FAT2은 동일한 데이터를 가지며 FAT는 1만 존재할 수도 있음
  • Root Directory : 파일시스템의 최상위 디렉토리. FAT12/16의 경우 섹터단위로 설정할 수 있고, FAT32의 경우 클러스터 체인으로 구성함.
  • FSInfo : FAT32에만 존제하는 영역으로 FAT32에 속하는 기타 정보를 포함하는 영역
  • Backup Area : FAT32에만 존재하는 영역으로 PBR부터 FSInfo까지를 백업하는 영역. 완전히 복사하여 파일 시스템에 문제가 생기면 Backup 영역에서 데이터를 다시 복사하여 복원하는 역할

3.1 PBR(Partition Boot Record), BPB(BIOS Parmeter Block)

 PBR은 여러 이름으로 불리는데 다른 이름으로는 BPB라고도 한다. 옛날 도스 시절에 BIOS 콜을 통해 파티션에 대한 정보를 얻어오고 처리하고 했는데, 그 기본 정보가 되는 블럭이라서 저런 이름이 붙은 것 같다. 일단 여기서는 PBR이라고 하겠다.

 PBR과 MBR의 차이는 무엇일까? MBR은 하나만 존재하며 섹터 0에만 있고, PBR은 각 파티션의 시작에 존재하며 FAT에 대한 정보를 포함하고 있다는 것이 다르다. PBR에는 어떤 정보가 포함되어있을까? FAT Type에 따라 다르므로 각각 살펴보도록 하자.


 FAT16/32의 PBR에 포함된 데이터는 아래와 같다.

  1. /**
        FAT16에 대한 구조체
    */
    typedef struct fat16Struct
    {
        BYTE vbJumpCode[ 3 ];
        char vcCreatingSystemIdentifier[ 8 ];
        WORD wSectorSize;
        BYTE bSectorsPerCluster;
        WORD wReservedSectorCount;
        BYTE bNumberOfFATs;
        WORD wNumberOfRootDirectoryEntries;
        WORD wTotalSectors;
        BYTE bMediumIdentifer;
        WORD wSectorsPerFAT;
        WORD wSectorsPerTrack;
        WORD wNumberOfSides;
        DWORD dwNumberOfHiddenSectors;
        DWORD dwTotalSectors;
  2.     // 여기 위까지는 FAT16/32 공통
        BYTE bPhysicalDiskNumber;
        BYTE bReserved;
        BYTE bExtendedBootRecordSignature;
        char vcVolumeIDNumber[ 4 ];
        char vcVolumeLabel[ 11 ];
        char vcFileSystemType[ 8 ];
        BYTE vbReservedForSystemUse[ 448 ];
        BYTE vbSignatureWord[ 2 ];
    } FAT16, * PFAT16;
  3. /**
        FAT32에 대한 구조체
    */
    typedef struct fat32Struct
    {
        BYTE vbJumpCode[ 3 ];
        char vcCreatingSystemIdentifier[ 8 ];
        WORD wSectorSize;
        BYTE bSectorsPerCluster;
        WORD wReservedSectorCount;
        BYTE bNumberOfFATs;
        WORD wNumberOfRootDirectoryEntries;
        WORD wTotalSectors;
        BYTE bMediumIdentifer;
        WORD wSectorsPerFAT;
        WORD wSectorsPerTrack;
        WORD wNumberOfSides;
        DWORD dwNumberOfHiddenSectors;
        DWORD dwTotalSectors;
  4.     // 여기 위까지는 FAT16/32 공통
        DWORD dwSectorsPerFAT32;
        WORD wExtensionFlag;
        WORD wFSVersion;
        DWORD dwRootCluster;
        WORD wFSInfo;
        WORD wBackupBootSector;
        BYTE vbReserved[ 12 ];
        BYTE bPhysicalDiskNumber;
        BYTE bReserved;
        BYTE bExtendedBootRecordSignature;
        char vcVolumeIDNumber[ 4 ];
        char vcVolumeLabel[ 11 ];
        char vcFileSystemType[ 8 ];
        BYTE vbReservedForSystemUse[ 420 ];
        BYTE vbSignatureWord[ 2 ];
    } FAT32, * PFAT32;

 상당히 많은 데이터를 포함하고 있는데, 일단 FAT16/32에 공통인 부분부터 살펴보자.

  • BYTE vbJumpCode[ 3 ] : Jump Code. 0xEB 0x?? 0x90 또는 0xE9 0x?? 0x??으로 구성되어야 함(이 부분을 제대로 넣지 않을 경우 윈도우에서 파티션 인식이 제대로 안됨)
  • char vcCreatingSystemIdentifier[ 8 ] : Format을 수행한 OS의 이름. 대충 집어넣으면 됨. "MSWIN4.1"와 같은 값.
  • WORD wSectorSize : 섹터 하나의 크기. 보통 512byte
  • BYTE bSectorsPerCluster : 클러스터를 구성하는 섹터의 수. 1Byte이므로 최대 255개까지 클러스터로 설정가능하나 1, 2, 4, 8, 16, 32, 64, 128이 일반적으로 유효한 값.
  • WORD wReservedSectorCount : 파티션 시작 영역부터 FAT 1영역이 시작되기 전에 존재하는 섹터의 수(위 그림 참조). FAT12/16에서는 1, FAT32에서는 32로 권장. 하지만 0xFFFF까지 값을 가질 수 있음. 이 값을 이용하면 Root Cluster의 시작을 적당한 위치로 설정할 수 있음
  • BYTE bNumberOfFATs : File Allocation Table(FAT)의 개수. 1개 또는 2개가 설정 가능하나 일반적으로 2의 값을 가짐.
  • WORD wNumberOfRootDirectoryEntries : Root Directory의 Entry의 개수. FAT12/16에서 사용하며 FAT16에서는 512 권장. FAT32에서는 0.
  • WORD wTotalSectors : 파티션의 크기가 0xFFFF 섹터 이하이면 이 필드 사용. FAT32에서는 0.
  • BYTE bMediumIdentifer : Media의 Type. 일반적으로 0xF8 사용.
  • WORD wSectorsPerFAT : FAT12/16에서 사용되는 값. FAT32에서는 0.
  • WORD wSectorsPerTrack : Track에 포함된 섹터의 수.
  • WORD wNumberOfSides : Size의 개수. 일반적으로 Cylinder의 수.
  • DWORD dwNumberOfHiddenSectors : 파티션 시작 이전에 존재하는 섹터의 수.
  • DWORD dwTotalSectors : 파티션의 크기가 0xFFFF 초과일때 사용되는 필드. FAT32에서는 반드시 이 필드 사용.
  •  BYTE bExtendedBootRecordSignature :  0x29 값으로 설정.
  • char vcVolumeIDNumber[ 4 ] : Volume ID. 일반적으로 일자/시간을 섞어서 만듬. 대충 만들어도 됨.
  • char vcVolumeLabel[ 11 ] : Volume Label. 볼륨 이름.
  • char vcFileSystemType[ 8 ] : "FAT12", "FAT16", "FAT", "FAT32" 같은 문자열.
  • BYTE vbSignatureWord[ 2 ] : 0x55 0xAA

 공통인 부분들에 대해 살펴봤으니, 이제 FAT32에 특화된 부분을 보자

  • DWORD dwSectorsPerFAT32 : FAT32용 FAT 영역 크기를 설정하는 부분
  • WORD wExtensionFlag : FAT1/2 영역이 존재할때, 하나만 사용할 것인지 아니면 둘다 동기화 해서 사용할 것인지 설정하는 플래그. 일반적으로 0으로 설정하여 둘다 동기화 하여 사용하는 것으로 설정.
  • WORD wFSVersion : File System Version. High Byte는 Major, Low Byte는 Minor를 나타냄. 일반적으로 0x00 0x00으로 설정.
  • DWORD dwRootCluster : Root Cluster의 번호. 일반적으로 2로 설정(클러스터 0과 1번은 Signature 같은 용도로 사용).
  • WORD wFSInfo : FSInfo가 위치하는 Sector Offset. 일반적으로 PBR 바로 뒤에 위치하므로 1의 값을 가짐.
  • WORD wBackupBootSector : Backup 영역이 존재하는 Sector Offset. 일반적으로 6의 값을 가짐.
  • BYTE vbReserved[ 12 ] : 예약된 영역. 무조건 0으로 설정.
  • BYTE bPhysicalDiskNumber : Drive Number. 일반적으로 0x80을 가짐.
  • BYTE bReserved : 예약된 영역. 무조건 0으로 설정.

  위의 필드 값을 FAT Type에 따라 PBR에 설정해 주면 반은 끝난 것이다. 약간 주의할 점은 Reserved Sector에 값을 설정했다면 파티션의 시작부터 Reserved Sector에 설정된 값만큼을 0으로 초기화해야한다(적극 권장). 위의 설명에도 나와있듯이 Reserved Sector의 값은 파티션의 시작부터 FAT1/2 이전까지의 섹터 수이므로, 절대 0이 될 수 없다. 왜? PBR이 있기 때문에 @0@)/~!!! 아무리 작아도 1 이상의 값을 가진다.

 이제 다음 메타 데이터를 살펴보자.


3.2File Allocation Table(FAT) 1/2 영역

 FAT 1/2 영역은 클러스터의 개수에 따라서 영역의 크기가 달라진다고 이야기 했다. 여기에서 말하는 클러스터의 개수는 실제 사용가능한 클러스터의 개수를 이야기하는데, 이 크기 이상만 된다면 얼마든지 좀 크게 잡아도 상관없다.

 FAT12의 경우 FAT를 구성하는 클러스터 링크의 비트수가 12bit가 이고, FAT16의 경우  16bit, FAT32의 경우 32bit이다. 따라서 한 섹터를 기준으로 FAT Type에 따라서 포함할 수 있는 클러스터 링크의 개수는 아래와 같이 된다.

  • FAT12 : 512Byte * 8 / 12 = 341.3333 개
  • FAT16 : 512Byte * 8 / 16 = 256 개
  • FAT32 : 512Byte * 8 / 32 = 128 개

 위에서 보는 것과 같이 FAT32로 갈수록 한 섹터에 담을 수 있는 클러스터 링크의 개수가 작아진다. 이것은 동일한 클러스터의 크기를 사용한다면 대용량일수록 FAT의 크기가 커진다는 것을 의미하고 FAT가 커지면 커질수록 실제로 사용가능한 클러스터의 크기가 줄어들게된다. 클러스터의 크기를 적당히 조절하여 FAT 크기를 너무 크지않게 하는 것이 좋다.

 FAT의 0번째 클러스터 링크와 1번째 클러스터 링크는 Signature의 용도 비슷하게 사용되는데, FAT Type에 따라 아래와 같이 설정해 준다.

  • FAT12 : 0xFF8, 0xFFF
  • FAT16 : 0xFFF8, 0xFFFF
  • FAT32 : 0xFFFFFFF8, 0xFFFFFFFF

 자 그럼 이제 FAT의 실제 크기를 한번 계산해 보자. 가장 간단하게 계산할 수 있는 방법은 파티션 전체의 크기를 클러스터의 크기로 나누어 구하는 방법이다. 실제로 이렇게 구하면 PBR + Rerserved Area + FAT1/2 영역의 크기도 사용가능한 것으로 인식하여 계산하기 때문에 낭비가 좀 있지만 계산은 편리하다. 특히 Root Directory의 시작 위치를 맞추거나 할때는 이렇게 계산하여 FAT의 크기를 구하고 여기에 Reserved Area의 값을 조절하여 맞출 수 있어 편리하다.

 또다른 방법은 전체 크기에서 PBR과 Reserved 영역을 제외하고 구하는 방법이다. 낭비가 좀 줄어들긴 한데, 식이 복잡해 진다. 아래는 그 계산 식이다(511은 올림을 위해 넣었다)

FAT의 크기(섹터) = [ ( 전체 파티션 크기(섹터) - PBR(1섹터) - Reserved Sector(?섹터)  )  / 클러스터의 크기(섹터) * 클러스터 링크의 크기 + 511 ] / 512

 이렇게 계산된 크기를 PBR에 wSectorsPerFAT나 dwSectorsPerFAT32 영역에 넣어주면 된다. 만약 wNumberOfFAT의 값을 2로 설정했으면 FAT1/2 영역을 연속해서 만들어줘야 하며 위의 FAT의 크기 * 2 만큼의 영역을 할당해 줘야 한다.



3.3 Root Directory Sector or Cluster 영역

  FAT16/32의 경우 위의 순서대로 PBR, FAT1/2 를 만들고 Root Directory Sector만 생성해 주면 정상적으로 윈도우에서 인식이 가능하다. 만약 Volume Label을 "NO NAME"으로 입력한 경우 Root Directory는 0으로 초기화 해주는 것으로 충분하다. 하지만 Volume Label을 사용한다면 Directory Entry Structure를 생성해서 Volume Label을 삽입해야 한다.


 Directory Entry Structure는 아래와 같이 구성되어있다.

  1. typedef struct directoryStruct
    {
        char vcNameAndExtension[ 11 ];
        BYTE bAttribute;
        BYTE bReservedForNT;
        BYTE bCreatedTimeTenth;
        WORD wCreatedTime;
        WORD wCreatedDate;
        WORD wLastAccessDate;
        WORD wStartingClusterNumberHigh;
        WORD wTimeRecorded;
        WORD wDateRecorded;
        WORD wStartingClusterNumberLow;
        DWORD dwFileLength;
    } DIRECTORY, * PDIRECTORY;

 각 항목은 아래와 같은 의미를 가진다.

  • char vcNameAndExtension[ 11 ] : 파일 이름과 확장자 또는 Volume Label 저장. 0번째 값이 0x00 or 0xE5이면 Free Entry.
  • BYTE bAttribute : Entry의 속성을 표시. 여러가지가 있음(타입은 아래 참조)
  • BYTE bReservedForNT : NT를 위해 사용되는 필드. 0의 값으로 설정.
  • BYTE bCreatedTimeTenth : 생성된 초. 1/10초 단위까지 저장.
  • WORD wCreatedTime : 생성된 시간(포맷은 아래 참조)
  • WORD wCreatedDate : 생성된 날짜(포맷은 아래 참조)
  • WORD wLastAccessDate : 마지막으로 접근한 날짜(포맷은 아래 참조)
  • WORD wStartingClusterNumberHigh : 클러스터의 상위 16bit 번호
  • WORD wTimeRecorded : 마지막으로 쓴 시간(포맷은 아래 참조)
  • WORD wDateRecorded : 마지막으로 쓴 날짜(포맷은 아래 참조)
  • WORD wStartingClusterNumberLow : 클러스터의 하위 16bit 번호
  • DWORD dwFileLength : 파일의 크기

 조금 복잡한데, 일단 Attribute 부터 보면 아래와 같이 나와있다(첨부 항목에 White Paper 참조).

DIR_ATTRIBUTE.PNG

 일단 포맷 후에 Volume Label을 생성해야 하므로 ATTR_VOLUME_ID를 생성하면 된다. 이때 주의할 것은 Volume Label을 설정하는 Directory Entry의 경우 Name과 Attribute를 제외한 나머지는 모두 0으로 설정해야한다.

 위를 보면 낯 익은 값들도 있을 것이다. 만약 윈도우가 FAT Filesystem으로 포맷되어있다면 위의 항목들이 설정된 Directory Entry 구조체가 여기저기 널려있을 것이다. Hex Editor와 같은 프로그램을 이용해서 하드디스크를 열어서 확인해 보자 @0@)/~~!!!!. 각 항목에 대한 자세한 설명은 White Paper를 참조하자.


 Time과 Date 부분은 공통적인 포맷을 사용하는데, White Paper에 아래와 같이 나와있다(간단한 비트 연산으로 만들 수 있다).

DIR_DATETIME.PNG

 파일 시스템 분석을 하는 경우라면 ClusterNumber와 Name, 그리고 Attribute를 유심히 봐두는 것이 도움이 될 것이다. 다른 파일 시스템이 그러하듯이 Root Directory로부터 Sub Directory가 생성되고 트리 형태로 관리되기 때문에 Root Directory를 찾은 다음 Entry 구조만 안다면 전체를 Travel 하는 것은 어렵지 않으니까...


3.4 FSInfo

  FSInfo 영역은 FAT32에만 존재하는 영역이다. 역시 한 섹터 크기정도로 되어있고 별다른 정보를 포함하지 않는다. 단지 FAT32에 참고할만한 정보만 가지고 있다.

  1. typedef struct fsInfoStruct
    {
        BYTE vbLeadSignature[ 4 ];
        BYTE vbReserved1[ 480 ];
        BYTE vbStructureSignature[ 4 ];
        DWORD dwFreeClusterCount;
        DWORD dwNextFreeCluster;
        BYTE vbReserved2[ 12 ];
        BYTE vbTrailSignature[ 4 ];
    } FSINFO, * PFSINFO;

  각 항목은 아래와 같은 의미를 가진다.

  • BYTE vbLeadSignature[ 4 ] : 0x52 0x52 0x61 0x41 설정
  • BYTE vbReserved1[ 480 ] : 예약된 영역. 0으로 설정.
  • BYTE vbStructureSignature[ 4 ] : 0x72 0x72 0x41 0x61 설정
  • DWORD dwFreeClusterCount : Free한 클러스터의 개수 저장. 알 수 없을 경우 0xFFFFFFFF. 권장 값이므로 100% 신용하면 안됨.
  • DWORD dwNextFreeCluster : Free한 클러스터의 첫번째 번호. 알 수 없을 경우 0xFFFFFFFF. 권장 값이므로 100% 신용하면 안됨.
  • BYTE vbReserved2[ 12 ] : 예약된 영역. 0으로 설정.
  • BYTE vbTrailSignature[ 4 ] : 0x00 0x00 0x55 0xAA 설정

 위에서 보는 것과 같이 FAT32의 부가적인 정보가 포함된 영역이고 특히 클러스터 관련 필드는 권장값이므로 절대 100% 믿으면 안된다.


4.마치며...

 여기까지 간단하게 FAT Filesystem에 대해서 알아보았다. 원래 훨씬 일찍 마무리 되었어야 하는데... 과제하느라 정신이 조금 없어서 찔끔 찔끔 정리하다보니 이제야 마무리를... ㅜ_ㅜ... 다소 부족한 감이 있지만 Formatter를 개발하면서 알아낸 정보를 기반으로 작성하였다.

 다음에는 위 정보를 기반으로 실제 FAT Filesystem을 분석해 보도록 하자.


5.첨부




이 글은 스프링노트에서 작성되었습니다.

이런게 있네... ㅡ_ㅡ;;;

83a8: e3a00006 mov r0, #6 ; 0x6
83ac: eaffffff b 83b0
83b0: e91ba800 ldmdb fp, {fp, sp, pc}

내가 C 소스 코드에서 무엇을 했는고 하니.. ㅡ_ㅡ;;;

return 6;

했더랬다. 저 어셈코드를 보면, 사실 mov r0, #6를 하고 ldmdb fp, {fp, sp, pc} 하면
될것을 return 을 했다고 폴짝 바로 아랫줄로 뛰어들고 있음을
"확인"
할 수 있다. 얼래.. ㅡ_ㅡ;;; 머지.. 저런식으로 코드를 생성하면 먼가 이득이 있나??
아님 내가 멀 잘못알고 있는건가??
설마 brench 명령으로 CPU Cache를 Flush하는 그런 말도안되는.. ㅡ_ㅡ;;;;;
내가 써놓고도 좀 말이 안되는거 같네. 만약 Flush를 위함이라하면 brench가 도배되
어야 정상이지......
O1을 줘서 약간의 Optimizing을 하면.. 아래와 같은 결과가 나온다.

8310: e3a00001 mov r0, #6 ; 0x6
8314: e91ba800 ldmdb fp, {fp, sp, pc}

컥.. brench가 온데간데 없다. @0@/~
이.. 이럴수가..





??

오늘도 역시나 열심히 NDS용 그래픽 라이브러리를 손보다가 문득 지난번에 만들어 놓은 고속 복사 함수를 적용시켜보면 어떨까 하는 생각이 들어서 LDMIA, STMIA 함수를 이용해서 메모리를 전송하는 소스를 넣어봤다.

LCD의 해상도고 256 * 192 이고 한 점이 2Byte로 구성되므로 총 98304 Byte, 즉 96 KByte가 되는데 이것을 memcpy()로 복사하니 대략 7 ~ 8 ms 정도가 걸렸다.

이것을 내가 만든 함수로 교체하니 4 ms 로 줄어들었다. @0@)/~

덕분에 약간의 속도 향상이... ㅜ_ㅜ...

아아~ 아직 죽지 않았어.. ㅜ_ㅜ....

오늘 어찌하다가 집에 가지 못해서... 어제 하던 윈도우 시스템이나 마저 손볼려고 코드를 열었다.

그때가 11시쯤이었던가... 지금이 7시니까 대충 8시간쯤 삽질했네...

뭐 그래도 소득은 있으니까... ㅎㅎ

BitBlt 기능을 DC에 추가해서 윈도우에 스킨 입히는 작업과 NDS에서 사용하기위한 그래픽 포맷(Kkamagui Nds Graphic - KNG)을 대충 만들고 변환해주는 프로그램을 만들었다.

그리고 윈도우가 많아져서 깜빡임이 심해지는 걸 느끼고 내친김에 더블 버퍼링까지...

하드코어로 작업했기 때문에 속도가 그리 빠른 편은 아니지만... 그래도 얼추 쓸만은 하다.

아래는 스크린 샷...

사용자 삽입 이미지


ps) 아까 아는 형이 좀 쉬라고 하던데... 이것도 병이라고... ㅡ_ㅡ;;;

정말 그런듯... 왠지 허접한 기기만 보면 기능 확장하고 싶은 충동이... ㅜ_ㅜ...

프로그래머가 천직인가....

NDS에 쉘을 만들어보려고 고민하던중에, KKAMAGUI Notepad 프로그램을 만들면서 썼던 허접 윈도우 라이브러리를 사용하면 쉽게 개발할 수 있을 듯한 생각이 들었다.

어디까지 구현한지 가물가물해서 소스를 뒤지고 있는데...

얼래... ㅡ_ㅡ;;; 거의 구현 안되어있는 것과 마찬가지....

노트패드 기능 구현한다고 윈도우 껍데기나 겨우 만들어 놓은 상태랄까...

클립핑 처리는 전혀 안되있고.... ㅡ_ㅡ;;;

그래서 일단 클립핑부터 시작했는데, 이게 장난이 아니더라....

구글링해서 찾은 알고리즘은 제대로 동작안해서 또 삽질하고... ㅜ_ㅜ...

우의곡절끝에 겨우 0.1 버전을 완성할 수 있었다.

기능은 클립핑 처리 + 윈도우 Z Order 지원 + 터치스크린을 이용한 윈도우 이동 및 종료 등등이다.

내일은 좀더 손봐서 PNG 파일 포맷을 읽어 표시할 수 있도록 해야겠다.

사용자 삽입 이미지
NDS의 윈도우 라이브러리를 손보려고 코드를 고치다가...

얼래... 잘되던 코드가 안되는 문제를 발견했다.

한참을 디버깅하다가... 코드의 순서를 살짝 바꾸니 이상한 데이터가 덤프되는 것을 발견하고...

Optimazation 할때 스택쪽에 문제가 생기거나 Register를 잘못 사용하고 있는 것이 아닌가 추측...

옵션을 O2에서 O1으로 낮춘 다음 전부 다시 컴파일하여 실행하니....

아무 문제 없이 실행되었다 @0@)/!!!!!

이런... ㅜ_ㅜ... 내 시간 돌려도.. ㅜ_ㅜ
여자친구가 생일선물을 해준다고 하길래 PSP를 중고로 사달라고 할까 고민하다가 이미 NDS를 가지고 있는지라 쓰지 않을 것 같은 생각이 들었다.

그래서 그냥 NDS에 메모리나 더 꼽을까 하고 G 마켓을 뒤졌는데...

어라? 왠 확장팩이 나왔다. 3 in 1 Expansion Pack for EZ-Flash라는 물건인데, 진동 + 메모리 확장 + GBA 팩 기능까지 하는 모양이다.

좀더 확실히 알기위해서 구글 형께 부탁했더니 아래와 같은 사이트를 보여줬다.

http://wiki.gbatemp.net/index.php?title=3_in_1_Expansion_Pack_for_EZ-Flash_V

사용자 삽입 이미지

뭐 진동이나 GBA를 할 수 있다는 그런건 별로 안땡기고... 램을 확장할 수 있는 점이 홈브루를 개발하는 나에게 가장 큰 장점인듯....

과연 얼마나 확장될까? 위의 사이트에 따르면...
  • 256 Mb (32 MB) of NOR Flash Memory. This type of memory is able to retain data without requiring uninterrupted power. Depending on data size, writing may take up to several minutes. One typical use includes copying over a GBA ROM, thereby allowing the 3-in-1 to act like a real GBA cartridge.
  • 128 Mb (16 MB) of PSRAM. This memory does not retain data when the power is turned off. However it can be written at speeds much faster than NOR memory.
  • 4 Mb (512 KB) of battery backed SRAM for save data. The battery is necessary to retain data.
  • Programmable embedded "rumble pak" (haptic feedback) device

무려 16MByte @0@)/~!!!

NDS 자체의 램이 4MByte 정도니까 합이 20MByte @0@)/~!!!!!

두둥... PSP가 32MByte인 것을 감안할 때 굉장한 붐업이다...

ㅜ_ㅜ... 당장 질러서 테스트 프로그램이나 하나 만들어봐야겠다...

다들 기대하시라 ㅎㅎ

>ㅁ<)/~!!!

이럴수가... 다시 재발했다.. @0@)/~

예전보다야 나아졌지만 화면 우측에 필기를 하면 튀는 현상이 생긴다.

이렇게 되면 결국 Z 축(누르는 압력)을 이용해서 계산하는 수 밖에 없는데....

결국 쓰긴 써야하나....


터치 스크린에 어중간한 압력이 들어갔을 때, 엄한 값이 나오는듯 한데...

세게 눌러서 필기를 하면 괜찮은 것 보니....

아우... 머리야... 또 수정해야겠군....
크윽... 얼마전까지 Vendor Request를 통해 데이터를 주고받는게 가장 간단하다고 생각하고 있었다.

그래서 드라이버를 뚝딱뚝딱 만들고 펌웨어 올리고 이렇게 작업해서 갔더니만... 오늘 선배가 HID Firmware하고 Report 패킷을 이용해서 데이터를 주고받는 프로그램을 만들었고.. ㅜ_ㅜ

어흑... 이런이런... 낭패...
난 왜 그생각을 못했을까....

이런 삽질.. ㅜ_ㅜ
LCD와 Graphic에 관련된 Power는 ARM 9에서도 건드릴 수 있었는데...

전체적인 System의 Power 관리(LED 포함)는 SPI를 이용해서 Power Management Device로 전송해야 한다...

아래는 SPI에 관한 내용... ARM 7을 통해서만 가능...

http://nocash.emubase.de/gbatek.htm#dsserialperipheralinterfacebusspi


아래는 Power Device에 관한 내용...
LED 색깔 바꾸는거, 깜박이는거... Shutdown 하는거 등등 가능...
http://nocash.emubase.de/gbatek.htm#dspowermanagement

시간나면 해봐야 겠다.

basicARM7 코드가 굉장히 간단하게 되어있던데...
소스를 얼핏 보니까 LCD의 HSync Interrupt를 받아서 Touch의 값을 읽도록 되어있었다.
혹시 이것때문에 LCD의 값이 튀는게 아닐까?
Touch의 Interrupt를 받아서 값을 읽으면 더 나을수도.... ㅡ_ㅡa...

일단 생각해 보자...
대단하다... 이미지 돌리기부터 해서 확대... 축소 같은 기능도 구현되어있다.. @0@)/~

이거라면 데이터 시트 같은 것도 NDS에 넣어 다니면서 볼 수 있겠던데....

크윽... 너무 좋은거 아냐.. ㅜ_ㅜ...
크아... libfat Library에 버그를 발견했다.

첫번째 버그는 파일을 열자마자 fseek()로 제일 처음으로 이동한다음, 다시 fseek()로
제일 마지막으로 옮겨간 후, write를 하면 정상적으로 write가 되지 않는 버그이고...

다른 한가지는 파일 끝에서 데이터를 쓰면 파일이 커지긴 하는데 쓰레기 데이터가
채워져서 커지는 버그이다.

일단 이 릴리즈 전버전으로 해서 다시 테스트 해보고 소스를 수정하던지...
아님 짜던지 해야겠다. ㅜ_ㅜ

아놔... 오늘도 하루를 다 날렸네.. ㅜ_ㅜ
invalid-file

파일 다운로드



흐.. 이런... libfat의 버그를 찾다 찾다 결국 그냥 포기...
(사실 귀찮아서 소스 보기를 포기... ㅡ_ㅡ )

버그를 우회하는 식으로 해결했다.
이놈이 글쎄.. fopen으로 r+ 옵션으로 열어서 파일 끝에서 데이터를 추가하면...
이상하게 변한다.... ㅡ_ㅡa.. 캐쉬 정책이랑 실제 flash write하는 기능이
제대로 동작하지 않는거 같기도 하고.... ㅜ_ㅜ...

그래서 파일 끝에서 추가할때는 a+ 옵션을 줘서 일부러 클러스터를 다 따라가게
만들고, 추가없이 파일을 수정만때는 r+ 옵션으로 열어서 바꾸도록 했다.

이렇게 하니 별 이상없이 동작하는구나... ㅜ_ㅜ...

크윽.. 젠장... 나중에 삼성과제 끝나고 나면 그걸 그대로 올려야 겠다.
역시... 내손으로 만드는게 좀더 믿음직 하네...

사용자 삽입 이미지
아우... 메모장 하나 만드는데 왜이렇게 오래 걸리는지... ㅡ_ㅡ;;;

메모장 하나 만들려고 윈도우 구조 다 세우고 Window base Class 만들고 CDC 만들고...
아주 난리다... ㅡ_ㅡa...

왜 이짓을 하는지 의문이긴한데... 어느정도 대충 가다는 나왔다는 ㅎㅎㅎ
이제 조금만 더하면 그림판 같은걸 만들 수 있겠다.

앗싸~ >ㅁ<)/~
libfat를 받아서 내 의사용 microSD io 코드를 추가한 다음
약간의 수정을 거쳐 만든 library 및 소스

테스트 결과....

이상없음~!!!

이로서 파일/폴더 관리 및 생성이 가능해졌다...

정말 대단하군.. @0@)/~

ZOrder 및 Window Frame을 구현한 간단한 윈도우 시스템을 구현했다.
정말 아주 간단한... ㅡ_ㅡa.. 그냥 윈도우 그리고 이동시켰을 때 처리 정도만
해놓은 버전...

나름대로 잘 동작해서 흐믓하다.
일단 윈도우 API와 비슷하게 구현했다.

그럭저럭 만족~ ㅎㅎ

사용자 삽입 이미지
Interrupt, Touch Screen, Button을 이용해서 간단한 메모장을 만들었다.

크으... 뭐 쉽진 않았지만... 기본적인 부분들은 어느정도 Library에서
구현 되어있었기때문에, 스펙을 보면서 구현하다가 잘 안되면 소스 뒤져서 확인하는 방식으로
진행했다.

여튼 나름 괜찮게 된다는거 ㅋㅋ
MicroSD 접근용 IO Interface 소스

출처 : http://chishm.drunkencoders.com/libfat/

libfat

A FAT library for the Nintendo GBA and DS

This is the successor to GBA NDS FAT. It features better reentrancy support, cleaner source code and is built as a proper library.

Installation

libfat is packaged as part of DevkitPro. Download the DevkitPro Updater and run it to start the installation. You will need to install as a minimum DevkitARM r20, libnds and libfat. I also suggest you install the GBA and NDS examples.

Using libfat in a project

The following assumes that you are using one of the example NDS templates.

The first step is adding libfat to the list of libraries. In the ARM9 Makefile (or the top level one if there is no specific ARM9 Makefile), look for the list of libraries. It should look like:

LIBS	:= -lnds9

Change this to:

LIBS	:= -lfat -lnds9

The order is important! Make sure that -lfat comes before -lnds9. The include directory will already be set, so you don't need to worry about this.

Next, you'll need to include fat.h in your main source file. Near the top of the file, insert the line:

#include <fat.h>

Before you can use any file functions, you'll need to initialise the library. You should only do this once within the execution of the program. Somewhere within the program's startup code, insert the line:

fatInitDefault();

This will initialise libfat and set the number of cached sectors to the default (8 on the DS, 2 on the GBA). It will also set libfat as the default stdio file device. If you prefer to use your own settings, use the line:

fatInit(cache_size, set_as_default);

In this case, cache_size is the number of sectors to store in the cache at any one time and if set_as_default is true it then libfat will be the default stdio file device.

Both fatInit and fatInitDefault return true if the library was successfully initialised and false otherwise.

That is all that's needed to get libfat running within your project.

Using files

Through the magic of DevkitARM and libfat, files can be openned like on any other POSIX system. Most of the functions in the stdio.h header should work. You do not need to worry about the cache. It will be taken care of, as long as you remember to close any open files before turning off the power.

Paths are separated by a forward slash -- / . Directories are specified by their path. The directory itself can be refered to as . and the parent as ... The root directory is simply / or /..

When libfat is not the default stdio device, you will need to refer to files and directories with a device specifier. This is done by using fat: before a path. You can also use a single digit in the device specifier, such as fat0: or fat1:. It is possible to use both slots at once on a DS. This is done by specifying the slot with a number. The full list of device specifiers is:

  • fat: -- the default device
  • fat0: -- same as fat:
  • fat1: -- the device in Slot-1 of the DS
  • fat2: -- the device in Slot-2 of the DS
  • fat3: -- a custom mounted device

To open a file called graphics.bin for reading within a directory called app_data located on the card in Slot-2, you would use:

FILE* test = fopen ("fat2:/app_data/graphics.bin", "rb");

If libfat is set as default, and you don't mind which slot the card is in, you could use:

FILE* test = fopen ("/app_data/graphics.bin", "rb");

If you are already in app_data (after a chdir("/app_data"), for example), you could use:

FILE* test = fopen ("graphics.bin", "rb");

Using directories

Directory functions do not follow POSIX standards. Custom functions are used for various reasons.

To add directory support to a project, you'll need to include <sys/dir.h>


To open a directory, use:

DIR_ITER* dp = diropen ("/directory/path/");

diropen returns NULL and sets errno on failure.


To iterate through a directory, use:

dirnext (dp, filename, &filestat);

dp is a previously openned directory, filename will be filled with the filename of the next file or directory, and filestat will be filled with the file's stats. If filestat is NULL, it won't be filled.

To start at the begining of a directory again, use:

dirreset (dp);

To close a directory, use:

dirclose (dp);

dirnext, dirreset, and dirclose all return 0 on success. If they fail for any reason, they will return -1 and set errno. dirnext will set errno to ENOENT if there are no file or directory names left in the directory.


The directory functions mkdir and chdir work as normal.

A quick file listing demo:

struct stat st;char filename[256]; // to hold a full filename and string terminator
DIR_ITER* dir;dir = diropen ("/");
if (dir == NULL) {
iprintf ("Unable to open the directory.\n");
}
else {
while (dirnext(dir, filename, &st) == 0) { // st.st_mode & S_IFDIR indicates a directory
iprintf ("%s: %s\n", (st.st_mode & S_IFDIR ? " DIR" : "FILE"),
filename);
}
}
허허... 이거 나원참....

ARM7쪽만 Touch Screen 쪽에 접근할 수 있어서 어찌 할까 고민중이었는데....
이런 대박이... ㅡ_ㅡa... libnds에서 이미 다 제공해 주는...

ARM7쪽 더미 코드를 둬서 이미 ARM9 쪽으로 IPC를 사용해서 넘기도록 되어있었다.
으으.... 그럼 일단 이건 그냥 쓰도록 하고...

ARM9쪽 코드를 우선적으로 libnds에 의존하지 않는 방향으로 수정하는게 나을듯도...
일단 그래 하던동...

+ Recent posts