오늘날 리눅스 커널에서 firmware를 사용하는 가장 광범위한 방법은 header file 에 static 하게 link 하는 것입니다.
이는 정책적으로 기술적으로 다음과 같은 이슈가 있습니다.
1. 드라이버의 firmware 는 업그레이드 되어 재배포 될 수 있습니다.
2. 비록 단 한번의 사용 일지라도 static 하게 link 된 firmware 는 영구히 메모리를 차지 합니다.
3. 사용자들은 firmware 를 메모리에서 해제하고, 드라이버를 제거하는 것에 대해 신경쓰지 않습니다.
그러한 이유로 request_firmware() 와 hotplug 간의 interface 나오게 된 것입니다.
다음의 리눅스에서 driver 와 hotplug 간의 일련의 절차 입니다.
kernel 에서 처리 :
driver 초기화 시에 request_firmware 함수를 호출합니다.
if(request_firmware(&fw_entry, $FIRMWARE, device) == 0) copy_fw_to_device(fw_entry->data, fw_entry->size); release(fw_entry); |
$FIRMWARE 는 파일 이름입니다. 이는 제조사에서 배포되는 특정 hw가 동작 되도록 하는 code image 일 것입니다.
request_firmware -> _request_firmware -> fw_setup_device 함수를 거치면서,
/sys/class/firmware/xxx/loading, /sys/class/firmware/xxx/data 파일을 생성합니다.
( hotplug 를 호출 하기 전에 firmware 를 __start_builtin_fw ~ __end_builtin_fw 영역에서 먼저 찾습니다.
이는 kernel 에 static 하게 포함된 firmware 들 중에 맞는 것이 있는지 먼저 검색합니다. 이 영역에 있다면
hotplug 관련 절차를 거치지 않습니다. )
그리고 사용자 공간의 hotplug 가 호출 됩니다.
request_firmware 함수는 block 됩니다.
( /sys/class/firmware/timeout 에 지정된 시간 만큼 입니다. )
사용자 공간 - hotplug 에서 처리 :
사용자 영역에서 /sys/class/firmware/xxx/loading, /sys/class/firmware/xxx/data 파일이 나타나며,
$DEVPATH, $FIRMWARE 는 환경변수로 전달 됩니다.
HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/ echo 1 > /sys/$DEVPATH/loading |
/sys/$DEVPATH/loading 에 1 를 write 하므로써, firmware 복사가 시작됨을 알립니다.
펌웨어 파일 $HOTPLUG_FW_DIR/$FIRMWARE 를 /sysfs/$DEVPATH/data 로 복사를 합니다.
/sys/$DEVPATH/loading 에 0 를 write 하므로써, firmware 복사가 완료됨을 알립니다. request_firmware 함수는 성공을 리턴합니다.
/sys/$DEVPATH/loading 에 -1 를 write 하면, 중지되며, request_firmware 함수는 실패를 리턴합니다.
kernel 에서 처리 :
request_firmware() 함수가 return 되면, fw_entry->data, fw_entry->size 에 firmware와 size 정보가 저장됩니다.
이를 driver 에서 특정 hw 에 맞는 작업을 수행하면 됩니다.
사용자 공간으로 전달되는 환경변수 :
SUBSYSTEM=module DEVPATH=/module/firmware_sample_driver LD_LIBRARY_PATH=:/user/app/lib PATH=/sbin:/bin:/usr/sbin:/usr/bin:/user/app/bin ACTION=add PWD=/ SHLVL=1 HOME=/ SEQNUM=933 _=/usr/bin/env |
정리 :
안드로이드 플래폼의 init 에서 uevent 를 이용하여, add 절차를 거치면서, firmware 를 필요로 하는 driver에서
firmware 를 전달 하는 과정(hotplug 와 driver 사이의 일어나는 일련의 절차)를 처리 해주고 있는 것입니다.
static int load_firmware(int fw_fd, int loading_fd, int data_fd) if(fstat(fw_fd, &st) < 0) <--(주석) fstat는 열린 파일이나 핸들과 연관된 디렉토리의 정보를 stat 구조체에 저장 //------------------------------------------------------------ //------------------------------------------------------------ nr = read(fw_fd, buf, sizeof(buf)); len_to_copy -= nr; nw = write(data_fd, buf + nw, nr); //------------------------------------------------------------ return ret; |
참고 :
kernel/Documentation/firmware_class/README
linux device driver model 관련 문서
'안드로이드 > 플랫폼' 카테고리의 다른 글
init 분석 open 하는 디바이스 - null, kmsg (0) | 2009.08.18 |
---|---|
init 분석 - 메인루프의 poll 의 timeout (0) | 2009.07.28 |
init 분석 - 안드로이드 보안 및 권한 (0) | 2009.07.28 |
프로세스, 기본 환경 (0) | 2009.07.28 |
안드로이드 부팅과정 (0) | 2009.07.28 |