ラベル Jaunty の投稿を表示しています。 すべての投稿を表示
ラベル Jaunty の投稿を表示しています。 すべての投稿を表示

☆バイナリファイルを書き換えてUSB無線LANクライアントを認識させる

このエントリに記載している方法は危険かもしれません。実施される方は自己責任で行ってください。

2010/06/01 追記
USB_DEVICEマクロを使ってIdVendor,IdProductの指定をしている
("__mod_usb_device_table"のmatch_flagsが0x03)
場合はこの方法で問題ないとおもわれますが、match_flagsの値がそれ以外の場合は十分でないようです。
hitoさんによる此方の投稿を参照してください。
https://forums.ubuntulinux.jp/viewtopic.php?pid=60947#p60947

Ubuntuでインストール後にすぐ使用できるコマンドだけでカーネルモジュールを直接書き換えて
USB無線LANクライアントを認識させる方法を下記に記述します。
(readelf,od,strings,perlおよびテキストエディタを使用)

成功例が一つ(rt2870sta)だけであるため、別のモジュールで有効であるか不明ですが、
どうしても有線LANの接続が確保できない場合やビルド環境の導入が困難である場合に
試してみる価値はあると思います。

使用するUSB無線LANクラアント(GW-USMicroN)がLucid,Karmicで
デフォルトで認識されてしまうので例はJauntyで実施しました。
カーネルは2.6.28-11-generic。GW-USMicroNのIDは2019:ed14です。
これだけでは心もとないので、Lucidで2019:ed14を取り除いたモジュールをビルドし、同じ要領を実施しました。
これも認識、接続に成功しています。
実はRalinkのドライバ(RT2870_LinuxSTA_V2.3.0.0.tar.tar.bz2)で試そうと思ったのですが、なぜかソースに2019:ed14を追加してビルドした場合でもGW-USMicroNで接続が出来ませんでした。(Lucid,Karmicとも)

前提条件は対象のUSB無線LANクライアントが使用しているチップを駆動するカーネルモジュールが既知で
あること。(そしてデフォルトでモジュールが存在するが、子機が認識されないこと。)
USB無線LAN子機のidVendor,idProductのペアがmodules.alias,modules.usbmapに
存在しない場合、下記の方法で接続できる可能性があります。

目次

●1.前置き(きっかけ)

●2.readelf,od,stringsで収集する情報

●3.書き換え作業

●4.モジュールの認識



●1.前置き(きっかけ)

きっかけはdepmodコマンドで更新される[/lib/modules/$(uname-r)/]のmodules.* にlsbusbで出力されるidVendor,idProductと同じ値を見つけたことに始まります。

当該の値が含まれているファイルはmodules.aliasとmodules.usbmapで下記のようなものでした。

■modules.aliasの内容
(先頭行と一部抜粋)
# Aliases extracted from modules themselves.
alias rt3070sta rt2870sta
alias usb:v0411p015Dd*dc*dsc*dp*ic*isc*ip* rt2870sta
alias usb:v1737p0077d*dc*dsc*dp*ic*isc*ip* rt2870sta
■modules.usbmapの内容
(先頭行と一部抜粋)
# usb module         match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info
rt2870sta            0x0003      0x148f   0x2770    0x0000       0x0000       0x00         0x00            0x00            0x00            0x00               0x00               0x0
rt2870sta            0x0003      0x1737   0x0071    0x0000       0x0000       0x00         0x00            0x00            0x00            0x00               0x00               0x0
rt2870sta            0x0003      0x1737   0x0070    0x0000       0x0000       0x00         0x00            0x00            0x00            0x00               0x00               0x0
rt2870sta            0x0003      0x148f   0x2870    0x0000       0x0000       0x00         0x00            0x00            0x00            0x00               0x00               0x0

これらの値はそれぞれdepmodコマンドがモジュールのファイルから読み出したものです。
depmodのソースから調べてみると下記の部分から取得していました。

■modules.aliasの元情報

モジュールの ".modinfo" セクションを元に作成されています。

$ readelf -p .modinfo モジュールファイルのパス
で簡単に見ることができます。

モジュールのソースにおていこの情報は
linux/module.hで定義されているMODULE_ALIASマクロを使って宣言されているようです。

#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)

#define MODULE_DEVICE_TABLE(type,name)  \
  MODULE_GENERIC_TABLE(type##_device,name)

■modules.usbmapの元情報

モジュールの"__mod_usb_device_table"シンボルに格納されています。
バイナリなので容易には見ることができません。
depmodを含むmodule-init-toolsのソースパッケージではtables.hで
その構造とサイズを定義しています。
(usb_device_id構造体、サイズはUSB_DEVICE_SIZE32,USB_DEVICE_SIZE64)

モジュールのソースにおていこの情報は
linux/usb.hで定義されている下記のマクロを使って宣言されているようです。

#define USB_DEVICE(vend,prod) \
 .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
 .idVendor = (vend), \
 .idProduct = (prod)

Ralinkのドライバ(RT2870_LinuxSTA_V2.3.0.0.tar.tar.bz2)では
USB_DEVICEを使用しているソースからMODULE_ALIASを使用するソースを
自動で生成しているようです。

●2.readelf,od,stringsで収集する情報

書き換え対象のidVendor,idProductとそのモジュール上の位置を知る必要があります。 ここでは"__mod_usb_device_table"シンボルの先頭のIDを対象にします。 そして対応する".modinfo"のエントリのオフセットを探します。

■モジュールの退避、バックアップの作成

対象モジュールを作業ディレクトリにコピーし、念のためバックアップを作っておきます。

$ sudo cp -p /lib/modules/$(uname -r)/kernel/drivers/staging/rt2870/rt2870sta.ko ./
$ TRG_MOD=./rt2870sta.ko
$ sudo cp -p $TRG_MOD ${TRG_MOD}.org
■"__mod_usb_device_table"の最初のエントリの位置と値の取得

まずreadelfコマンドで"__mod_usb_device_table"シンボルがが格納されている
セクションとその先頭からのオフセット、サイズを取得します。
コマンドの実行結果から25番目のセクションに格納されていて、
先頭からのオフセットが16進で0x4140、サイズが1220Byteであることが分かります。
(先頭だけを対象にするのでサイズは特に必要ありません。)

$ TRG_MOD=/lib/modules/2.6.28-11-generic/kernel/drivers/staging/rt2870/rt2870sta.ko
$ readelf -s $TRG_MOD | sed -ne '1,3p;/__mod_usb_device_table/p;'

Symbol table '.symtab' contains 1267 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
   555: 00004140  1220 OBJECT  GLOBAL DEFAULT   25 __mod_usb_device_table

25番目のセクションを探します。".data"セクションです。
ファイルの先頭から16進で0x6c980で始まっていることが分かります。
(別のモジュールで試してみると番号[Nr]はモジュールによって違いますが、
セクション名は".data"でした。基本的に".data"セクションを探せばよさそうです。)

$ readelf -S $TRG_MOD | sed -ne '1,4p;/\[25\]/p;'
There are 35 section headers, starting at offset 0x73830:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [25] .data             PROGBITS        00000000 06c980 004694 00  WA  0   0 32

開始アドレスを計算してodコマンドで内容を表示します。
1レコードが20Byteで先頭5項目はunsigned shortであることが分かっているので
(depmodのソースtable.h参照)
odのオプションに -N 20 --width=20 -t x2 を指定します。

ここで -t x1 とすると、x86はリトルエンディアンなのでunsigned shortの
上位バイトと下位バイトが逆になって表示されます。
出力から書き換え箇所はファイル先頭からのオフセットが十進で(461504 + 2) Byte
そこからunsigned shortを2つ分(計4byte)を書き換え対象にします。

$ perl -e 'print 0x4140 + 0x6c980 ,"\n"'
461504
$ od -j 461504 -N 20 -v -A d -t x2 --width=20 $TRG_MOD
0461504 0003 148f 2770 0000 0000 0000 0000 0000 0000 0000
■modules.aliasの元になる情報の書き換え位置

次にmodules.aliasの元になる情報の書き換え位置を調べます。
これは文字列なのでstringsコマンドに-tdオプションを指定することで
比較的簡単に調べることができます。
十進でファイルの先頭からのオフセット438048Byte,長さ20Byteを書き換えます。
("alias=usb:v148Fp2770" を "alias=usb:v2019pED14"へ)

$ strings -td $TRG_MOD | grep -i -e 148f.2770
 438048 alias=usb:v148Fp2770d*dc*dsc*dp*ic*isc*ip*

●3.書き換え作業

perlを使って書き換えを行ないます。

■"__mod_usb_device_table"の先頭書き換え

write_vp.plというスクリプトを書きました。
ネット接続不可の状況でも、その場ですぐにかけるような内容です。
書換え後のidVendor,idProductは直書きです。
引数は対象ファイルとオフセットです。

### スクリプト内容の表示
$ cat ./write_vp.pl
#!/usr/bin/perl

if($#ARGV != 1){
    print STDERR "usage $0 filepath offset\n";
}

my($file) = shift;
my($offset) = shift;

open FH, "+< " . $file or die "$!:$file";
seek(FH, $offset, 0);
my($buf) = pack "SS", 0x2019, 0xed14;
syswrite(FH, $buf, 4) or die "$!";

### 実行
$ sudo ./write_vp.pl $TRG_MOD 461506
### 確認
$ od -j 461504 -N 20 -v -A d -t x2 --width=20 $TRG_MOD
0461504 0003 2019 ed14 0000 0000 0000 0000 0000 0000 0000
■".modinfo"セクションの書き換え

write_alias.plというスクリプトを書きました。
write_vp.plと同じく短いものです。

### スクリプト内容の表示
$ cat ./write_alias.pl
#!/usr/bin/perl

if($#ARGV != 1){
    print STDERR "usage $0 filepath offset\n";
}

my($file) = shift;
my($offset) = shift;

open FH, "+< " . $file or die "$!:$file";
seek(FH, $offset, 0);
syswrite(FH,"alias=usb:v2019pED14",20);
seek(FH, $offset, 0);
sysread(FH,$buf,20);
print $buf,"\n";

### 実行
$ sudo ./write_alias.pl $TRG_MOD 438048
alias=usb:v2019pED14
### 確認
$ strings -td $TRG_MOD | grep -e 2019.ED14
 438048 alias=usb:v2019pED14d*dc*dsc*dp*ic*isc*ip*

●4.モジュールの認識

モジュールを正式な位置に書き戻してdepmodで依存情報を更新し、modprobeでモジュールを読み込みます。

$ sudo cp $TRG_MOD /lib/modules/$(uname -r)/kernel/drivers/staging/rt2870/
$ sudo depmod -a $(uname -r)
$ sudo modprobe rt2870sta

あとはNetworkManagerで認証関係の設定を行えば接続できるはずです。

☆gnome-sudokuの不具合修正

去年の11月にtwitterでつぶやいていたgnome-sudokuの不具合について、修正パッチを公開してみます。対象はubuntu jauntyに入っているバージョン2.26.1です。(karmicの場合は下の方に補足を書いています。)
すべてのソースを理解しているわけではありませんし、すべての機能をテストしているわけではありませんが、1ヶ月以上プレイしていておかしな点は出てません。(トラッカなどは使い方がわからないので.....)

gnome本家に報告したり、ppaを作ったりするのがより正しいユーザの在り方なのかもしれませんが、なにぶんわからないことが多いので......。
パッチが危険な動作をするようなことはありませんが、適用に当たってはすべて自己責任でおこなってください。

●不具合の概要

同一の行または列に番号のコンフリクトがある場合、その後から入力した方と同じボックス(3X3の領域)の別セルに同じ数値を入力しても赤くならない。
具体例は下図。反転しているセル(中心のひとつ上)は同一ボックスに同じ数字"1"があるのに赤くなっていない。

●修正方法

patchファイルを
https://sites.google.com/site/midspeclowload/files/sudoku.py.2_26_1.patch.txt?attredirects=0&d=1
に置きました。

対象のsudoku.pyは下記にあります。pythonのスクリプト(テキストファイル)です。
/usr/share/python-support/gnome-games-data/gnome_sudoku/sudoku.py

パッチを当ててから

sudo update-python-modules gnome-games-data
としてやれば使えるようになります。

既にgnome-sudokuを起動したことがあるとエラーが出るかもしれません。
その場合はホームディレクトリにあるsudoku関連のファイルを消してやると
起動するはずです。

find ~/ -name '*sudoku*'
で出てきたディレクトリをガリッと消して問題ないはずです。(必要なディレクトリは次に起動したときにまた作られます。)自分で作ったディレクトリやファイルを削除しないように気をつけてください。

●karmicについて

karmicに入っているgnome-sudokuは2.28です。2.26と同様の不具合があります。
加えてなぜか終了時に表示される経過時間がおかしかったりします。
さらに解けているはずなのに終了のダイアログが出なかったりします。
(2.26と同じ要領で修正する経過時間の件以外は直ります。)

経過時間のほうは直せそうにないので私は手作業で2.26を入れてます。これをやるとアップデートがあった場合に適用されません。しかしjauntyを使っている間、gnomeのゲーム関連でアップデートはみたことがないので多分問題ないでしょう。

(識者の方に怒られそうです。下記の説明はかなりはしょってますが、これでわからない方はやめておいた方がいいと思います。)

要領

1.synapticのゲームのカテゴリに入っているものをアンインストール。

2.jaunty用のdebを落としてきて、arで解凍、さらにdata.tgzをtarで解凍

control.tgzのなかのpostinstallを実行。ファイルは下記から
http://jp.archive.ubuntu.com/ubuntu/pool/main/g/gnome-games/gnome-cards-data_2.26.1-0ubuntu2_all.deb
http://jp.archive.ubuntu.com/ubuntu/pool/main/g/gnome-games/gnome-games-data_2.26.1-0ubuntu2_all.deb
http://jp.archive.ubuntu.com/ubuntu/pool/main/g/gnome-games/gnome-games_2.26.1-0ubuntu2_i386.deb

3.パッチを当てる。

です。ちなみにdpkgでインストールするとupdate-managerを起動したときに
アップグレードが不完全だと怒られます。しかもディストリビューションのアップデートをしないと通常のアップデートの適用ができません。

●修正内容の説明

入力した値がコンフリクトしているとclass SudokuGridに保持しているデータ(コンフリクトチェック用のset3つと盤面対応のlistのlist)には入力値を保持せずに例外を投げます(オリジナルの107行目から始まるaddメソッド参照)。GUI上は数値が入っているので問題の現象が起ります。

そこで、コンフリクトチェック用のsetはlistに変更(当然追加はaddでなくappend)、ただし終了判定などで要素の数をチェックしていたりするので基本的に参照時はset()でset型に直して使用。コンフリクトした場合でも要素の追加を行います。(これはあちこち直します。)

コンフリクトした場合でもチェック用のリストに要素の追加を行っているので、コンフリクトチェックのメソッドで自分自身をコンフリクト判定から除外するように修正します。(オリジナルの179行目から始まるfind_conflictsメソッド)