ASUS TransBook T101HA-G128 BIOSパスワードのリセット方法

投稿日:

 昨夜、寝床でPCを使用していた。先日購入したASUSの2 in 1ノート、「TransBook T101HA-G128」だ。夜中のこととて、イヤホンを挿入した。ところが、「オーディオ機器が接続されました」とのメッセージは表示されるのに、音が出ない。

 前のTransBook(T100Chi)では、タッチパネルが動かなくなることが多く、そういうときはBIOSのデフォルトをロードしなおして再立ち上げすると直った。時計が遅れる現象などもこれで直ったものだ。

 このPCもそうだろう、同じようにすれば直るのでは、と思い、BIOSセットアップ画面を出した。T100Chiと比べて、T101HAはキーボードがBluetoothではなく、物理接続なので簡単だ。電源投入直後、「ASUS」ロゴの表示画面で[F2]キーを押し下げながら起動すると、BIOSセットアップ画面が表示される。

 BIOSセットアップに入るためのパスワード画面が出る。一昨日、他人に悪用されることがないようにとBIOSパスワードをセットしておいたのだ。Administrator・User両方ともである。

 得たり、とセットしておいたAdministratorのパスワードを入力する。

 「Invalid Password」とはじかれる。あれ?慎重にもう1回……あれ?もう2回……

 パスワードは3回はじかれて、画面がフリーズした。

 電源を入れなおしては数回試みるが、同じである。

 幸いにUserパスワードのほうは正しくセットされていなかったらしく、無入力+EnterでBIOS画面だけは出すことができた。だが、Administratorではないので、デフォルト値ロードなどの肝心の選択肢が使えない。

 うーむ。参った……。

 ……と、いうようなわけで、ネットを渉猟し、「ASUS TransBook T101HA-G128」の「BIOSパスワードリセット方法」が分かった。

 検索して出てくる方法は、少し情報が古かったりするようなので、私が実行してうまくいった最新の方法をここに書き留めておきたい。多分、私と同じようなハメに(おちい)った人が、検索して役立てるだろう。

「ASUS TransBook T101HA-G128」のBIOSパスワードリセット方法
  1.  PCの日付を「2011年11月23日」にする。
  2.  ネットのほかの情報では「2002年1月2日にする」と書かれているものがあるが、私の環境ではなぜかうまくいかなかった。おそらく機種や発売時期で異なるのだと思われる。

  3.  再起動し、ASUSロゴ表示前に[F2]キーを長押し等する。長押しでうまくいかない場合は、間欠的に指を離してまた押す等するとよい。
  4.  パスワード入力画面が表示される。
  5.  なんでもいいので、何か文字を入力し、一旦Enterする。「Invalid Password」となる。Enterキーを押す。
  6.  (おもむろ)に [Alt] + R を入力する。(←重要!)
  7.  画面に「Enter Rescue password / 2011/11/23」と表示される。
  8.  「A1AAABBA」とパスワードを入力する。この際、シフトキー等を使用しない。
  9.   BIOSのAdministratorパスワードが解除された状態でBIOSセットアップが起動する。

 これで無事、自分のPCの支配権がすべて自分に戻ってくるのであった。めでたしめでたし。

その他の補足情報

 実は上記に行き着くまでに、ほかの方法もいろいろと試した。結局あまり意味はなかったが、副産物として後々参考になりそうな事項があったので、以下に書いておく。

BIOS等のバイナリファイルの16進及びASCIIダンプの取り方

 昔は「dump」などのコマンドがMS-DOSの拡張キットなどに入っていたと記憶するが、Windows 10のコマンドラインツールにはない。

 しかし、代替手段はある。証明書関連の諸作業に使用するコマンドの「certutil.exe」を使えばダンプをとることができる。

 例えば下記は、そのcertutil.exeを使用し、ASUSのサイトからダウンロードした本日現在最新のBIOSのダンプをとっているところである。

C:\>certutil -f -encodehex C:\T101HAAS.304 C:\T101HAAS.304.dmp
入力長 = 6293504
出力長 = 29824512
CertUtil: -encodehex コマンドは正常に完了しました。

 こうすると、「C:\T101HAAS.304.dmp」にテキストでダンプが取れるから、それを見て解析するとよい。注意すべき点は、バイナリ形式の中での文字列は、一文字ごとに0x00が入ったりすることなので、「ALAA」という文字列を探す場合は、「A.L.A.」……というふうに探さないと見つからない。また、改行も入るから、文字列を当てにしての検索はあまりうまくいかないと思ったほうがよい。

ASUS「WinFlash」で無理やりBIOSを書き換える方法

 実はBIOSを強制的に上書きすれば、BIOSのAdministratorパスワードもリセットされるのではないか、と思ったのだ。結果は「リセットされなかった」ので、無駄であった。ネットのQ&Aなどで「BIOSをアップデートすればパスワードもリセットされますよ」などという解答があったのだが、これは誤りとみてよい。また、機種等にもよるのであろう。

 だが、何か他のことで、BIOSを無理やり上書きしたいという人もいるかもしれないと思うので、その情報を書いておく。

 標記「WinFlash」はASUS純正のBIOSアップデートユーティリティだ。安全にできており、日付などでうまく制御され、無駄なダウングレードなどはできない仕組みになっている。

 しかし、コマンドラインオプションをつけて起動することで、強制的に書き換えたり、日付を無視してダウングレードなどすることができる。

 ネットでは「/nodate」オプションが第三者によって紹介されているが、このプログラムのダンプをとると、次のようなコマンドラインオプションがあることがわかる。

/nodate ダウングレード等のため、タイムスタンプを無視する。
/force 強制的に書き換え
/nowmsg 不明(メッセージの抑制ではないかと思われる)
/nodefault 不明

 私は上のうち、「nodate」と「force」の両方を試し、特にシステムが破壊される等の支障はなかった。BIOSはきれいに上書きされた。……パスワードは初期化されなかったので、意味はなかったが(苦笑)

 しかし、意味もなく上記のオプションをつけてWinFlash.exeを実行し、PCがおかしくなったとしても、私の知ったことではない。

cmospwd

 他に、「cmospwd」というフリーソフトを使ってCMOSをフラッシュする、という情報がネットに多く見つかるが、どうもASUS TransBook T101HA-G128には適合しないらしく、うまくいかない。「ioperm」というシステムのインストールを求められるのだが、それがうまくいかない。

他のパスワード

 ASUSのBIOSパスワードに関することはネットに情報があり、PCに設定する日付ごとにパスワードが変化するようである。

 実際に入力して試してはいないが、次のような情報がある。

日付 パスワード
2011-11-23 A1AAABBA
2011-11-24 AL11LAAA
2011-11-25 ADH0AHBB
2011-11-26 AAAAB1BL
2011-11-27 A9BOCAAD
2011-11-28 A0B0ADBD
2011-11-29 AADD0L2B
2011-11-30 L1DDO1AB
2011-12-01 0DADBALA
2011-12-02 LA9AC0BA
2011-12-03 L9L1ACAA
2011-12-04 B0L00ALA
2011-12-05 BBAAAA0B
2011-12-06 2ABOHBAL
2011-12-07 2OA0BALD
2011-12-08 1BADLL0D
2011-12-09 1H9A2BAB
2011-12-10 B9BA0BDB
2011-12-11 BBB1AAL0
2011-12-12 OBDH4LAL
2011-12-13 OAAABBDB
2011-12-14 AO2OLBL2
2011-12-15 AB40BAA1
2011-12-16 A4ADAHD1
2011-12-17 AABAO1LC
2011-12-18 AAB1AAA9
2011-12-19 A1DHDBDB
2011-12-20 AADHLHBA
2011-12-21 AOAAB1AA
2011-12-22 AL1BAADA
2011-12-23 A4HB0BBA
2011-12-24 AAADALAA
2011-12-25 AAOADABB
2011-12-26 A2021BBL
2011-12-27 B0D4ALAD
2011-12-28 BLAAB9BD
2011-12-29 LA1BAA2B
2011-12-30 BACBOBAB
2011-12-31 AAOLDOA0

耽るLチカ

投稿日:

 LEDは半導体であるから、電球と違って、光り始める前は抵抗は無限大であり、電流は流れない。ところが電圧がVfを超えて光り始めたら最後、抵抗がなくなって電源をショートさせた状態でぶっ飛び、自分自身も壊れる。従って必ず抵抗を一緒にくっつけてやるのだ。

 その抵抗を選ぶのは簡単で、基本的に E = I\cdot R という、この式のみでよい。LEDを買ってくると、流すべき電流値(If)、光り始める電圧(Vf)がどこかに書いてあるから、それに従って計算する。すなわち、

R = \frac{V - Vf}{If}

ここに、

V 自分が用意する電源の電圧
Vf 買ってきたLEDのVf(順方向電圧)、つまり光り始める電圧
If 買ってきたLEDのIf(順方向電流)、つまり光らせるために必要な電流

 ただ、抵抗は入手可能な数値が決まっており、そのものピタリという抵抗値のものは売っていない。なので、計算した値と一番近い抵抗を選び、その抵抗値で再び電流を計算して、買ってきたLEDのIfを超えていないかどうかを確かめる。

 これが、簡単な計算ではあるけどいちいち面倒くさい。

 それでまあ、抵抗を選ぶのにこういうスプレッドシートを作る。

 それから、これを使ってみよう。

IMG_3181

 これは、「武蔵野電波のプロトタイパーズ第15回『TLC5940で16個のLEDを遊ぶ』」で取り上げられている「TLC5940NT」というICだ。千石電商本店2階、入って左側の、一番奥のほうの抽斗で売られている。武蔵野電波のページでは400~700円とされているが、千石電商の店頭売りでは390円である。

 Arduinoで使うには、GitHubにあるライブラリをダウンロードし、zipを展開して出てくる「tlc5940」というディレクトリをArduino IDEのインストールディレクトリの下にある「libraries」の中にコピーすればよい。

 スペックシートはコレだが、スペックシートを見るより、Arduinoにライブラリを入れると出てくるようになるサンプルスケッチの「BasicUse」を見た方が分かり易いと思う。こんな風にサンプルは書かれている。

/*
    Basic Pin setup:
    ------------                                  ---u----
    ARDUINO   13|-> SCLK (pin 25)           OUT1 |1     28| OUT channel 0
              12|                           OUT2 |2     27|-> GND (VPRG)
              11|-> SIN (pin 26)            OUT3 |3     26|-> SIN (pin 11)
              10|-> BLANK (pin 23)          OUT4 |4     25|-> SCLK (pin 13)
               9|-> XLAT (pin 24)             .  |5     24|-> XLAT (pin 9)
               8|                             .  |6     23|-> BLANK (pin 10)
               7|                             .  |7     22|-> GND
               6|                             .  |8     21|-> VCC (+5V)
               5|                             .  |9     20|-> 2K Resistor -> GND
               4|                             .  |10    19|-> +5V (DCPRG)
               3|-> GSCLK (pin 18)            .  |11    18|-> GSCLK (pin 3)
               2|                             .  |12    17|-> SOUT
               1|                             .  |13    16|-> XERR
               0|                           OUT14|14    15| OUT channel 15
    ------------                                  --------

    -  Put the longer leg (anode) of the LEDs in the +5V and the shorter leg
         (cathode) in OUT(0-15).
    -  +5V from Arduino -> TLC pin 21 and 19     (VCC and DCPRG)
    -  GND from Arduino -> TLC pin 22 and 27     (GND and VPRG)
    -  digital 3        -> TLC pin 18            (GSCLK)
    -  digital 9        -> TLC pin 24            (XLAT)
    -  digital 10       -> TLC pin 23            (BLANK)
    -  digital 11       -> TLC pin 26            (SIN)
    -  digital 13       -> TLC pin 25            (SCLK)
    -  The 2K resistor between TLC pin 20 and GND will let ~20mA through each
       LED.  To be precise, it's I = 39.06 / R (in ohms).  This doesn't depend
       on the LED driving voltage.
    - (Optional): put a pull-up resistor (~10k) between +5V and BLANK so that
                  all the LEDs will turn off when the Arduino is reset.

    If you are daisy-chaining more than one TLC, connect the SOUT of the first
    TLC to the SIN of the next.  All the other pins should just be connected
    together:
        BLANK on Arduino -> BLANK of TLC1 -> BLANK of TLC2 -> ...
        XLAT on Arduino  -> XLAT of TLC1  -> XLAT of TLC2  -> ...
    The one exception is that each TLC needs it's own resistor between pin 20
    and GND.

    This library uses the PWM output ability of digital pins 3, 9, 10, and 11.
    Do not use analogWrite(...) on these pins.

    This sketch does the Knight Rider strobe across a line of LEDs.

    Alex Leone <acleone ~AT~ gmail.com>, 2009-02-03 */

#include "Tlc5940.h"

void setup()
{
  /* Call Tlc.init() to setup the tlc.
     You can optionally pass an initial PWM value (0 - 4095) for all channels.*/
  Tlc.init();
}

/* This loop will create a Knight Rider-like effect if you have LEDs plugged
   into all the TLC outputs.  NUM_TLCS is defined in "tlc_config.h" in the
   library folder.  After editing tlc_config.h for your setup, delete the
   Tlc5940.o file to save the changes. */

void loop()
{
  int direction = 1;
  for (int channel = 0; channel < NUM_TLCS * 16; channel += direction) {

    /* Tlc.clear() sets all the grayscale values to zero, but does not send
       them to the TLCs.  To actually send the data, call Tlc.update() */
    Tlc.clear();

    /* Tlc.set(channel (0-15), value (0-4095)) sets the grayscale value for
       one channel (15 is OUT15 on the first TLC, if multiple TLCs are daisy-
       chained, then channel = 16 would be OUT0 of the second TLC, etc.).

       value goes from off (0) to always on (4095).

       Like Tlc.clear(), this function only sets up the data, Tlc.update()
       will send the data. */
    if (channel == 0) {
      direction = 1;
    } else {
      Tlc.set(channel - 1, 1000);
    }
    Tlc.set(channel, 4095);
    if (channel != NUM_TLCS * 16 - 1) {
      Tlc.set(channel + 1, 1000);
    } else {
      direction = -1;
    }

    /* Tlc.update() sends the data to the TLCs.  This is when the LEDs will
       actually change. */
    Tlc.update();

    delay(75);
  }

}

 この最初のほうのコメントにアスキー・アートで書かれている図を見て結線するとよい。こんな感じだ。

IMG_3185

 LEDは秋葉原・千石電商の隣の店、「akiba LEDピカリ館」で売っていた10個入り300円の白色LEDで、Vfが3.0V~3.4V、Ifが20mAとある。電源が5Vならば100Ωばかり抵抗を付けてやればいい理屈だが、全部点灯させるとArduinoがダメになってしまうから、さらに絞って10KΩつけてやる。

 コンパイルして動かすとこうなる。

 10kΩでもこれくらい明るい。

 このICを使うと、パルス幅変調の幅も、Arduinoが256段階であるのに比べ、4096段階と格段に細かくなる。

 アレンジを加えてみよう。昨日買ってきたポテンショメータを使う。アナログの4番ピンと5番ピンに50kΩのポテンショメータと10kΩの抵抗をつなぎ、それぞれを強さと速さにして、「尾を引いたみたいに」明るさ制御をする。

 ポテンショメータの回路はこうする。

IMG_3191

 図の「E1」をアナログ入力で読めばよい。ポテンショメータのつまみの位置は、次の計算でR2を求めれば明らかになる。

E_{0} = I_{0}\cdot(R_{1} + R_{2})
I_{0} = \frac{E_{0}}{R_{1} + R_{2}}…①
I_{0} = \frac{E_{1}}{R_{2}}…②
① = ②
\frac{E_{0}}{R_{1} + R_{2}} = \frac{E_{1}}{R_{2}}
E_{0}\cdot R_{2} = E_{1}\cdot R_{1} + E_{1}\cdot R_{2}
R_{2}(E_{0} - E_{1}) = E_{1}\cdot R_{1}
R_{2} = \frac{E_{1}\cdot R_{1}}{E_{0}-E_{1}}

 組み付けるとこうなる。

IMG_3187

 動かすとこんな感じ。

 スケッチはこんな感じ。

//
//  wPotentio2tlc5940.ino
//    ポテンショメータとTLC5940でLチカ
//    27.08.02(日)0900~
//    佐藤俊夫
//
#include "Tlc5940.h"
//
const float
  R1 = 10000.0,     //  ポテンショメータ前の抵抗10kΩ, 
  E0 = 5.0,         //  電源電圧5V, 
  MAXVR = 50000.0;  //  ポテンショメータの最大抵抗
const unsigned int   VR1 = 4, VR2 = 5;  //  ポテンショメータはアナログピンのA4・A5
const unsigned int MAX_LED = 15;  //  LEDは0~15の16個
//
void setup()
{
  Tlc.init();
  pinMode(VR1, INPUT);
  pinMode(VR2, INPUT);
}

void loop()
{
  float vr1 = 0.0, vr2 = 0.0, e11 = 0.0, e21 = 0.0;
  static unsigned int topLed = 0, tailLen = 10;
  e11 = analogRead(VR1) * (5.0 / 1024);
  e21 = analogRead(VR2) * (5.0 / 1024);
  vr1 = (e11 * R1) / (E0 - e11);  //  明るさ
  vr2 = (e21 * R1) / (E0 - e21);  //  速さ
  if(++topLed > MAX_LED + tailLen)  topLed = 0;
  Tlc.clear();
  int bright = constrain(fmap(vr1, 0.0, MAXVR, 0, 4095), 0, 4095);
  Tlc.set(topLed, bright);
  for(int i = topLed - 1; i >= 0; i--){
    bright -= (4096 / tailLen);
    if(bright < 0) bright = 0;
    Tlc.set(i, bright);
  }
  Tlc.update();
  unsigned int delayTime = constrain(fmap(vr2, 0.0, MAXVR, 100, 10), 10, 100);
  delay(delayTime);
}
//
float fmap(float x, float in_min, float in_max, float out_min, float out_max) {
  //  もともとの「map()」がlong int型でこの用途に合わないので、float型を定義
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

空の写真リベンジ

投稿日:

 先週試したAdafruit製の「小型TTLシリアルjpegカメラ」での間欠撮影先週はどうしたわけか同じ画像ばかり撮れてしまい、失敗である。

 (チナミに、このカメラのメーカーの「Adafruit」という会社、有名なマッシモ・バンジのTEDの中で紹介されていたことに気付いた。)

https://youtube.com/watch?v=UoBUXOOdLXY%3Ft%3D5m50s

 気を取り直して、スケッチを直す。撮影時のカメラのステータスを確認し、撮れていなければ何回でも撮り続ける。

「while(撮れてない)撮る;」

……というわけだ。まあ、万が一ハードウェアエラーなどがあるとループが回り続けるので良くないが、ループが回り続けようが結局のところはモノとしては電源を入れ直す他にどうしようもないので、こんなものだろう。

 それと、撮影が終わったらカメラをそのつどリセットすることにした。また、既に存在するファイル名は避けるようにした。こういう時、Arduinoには書式文字列付きの「sprintf」がないので、少し不便だなと思う。

 夜明けから日没までの一日の空の雲を撮りたいので、天気予報を見て雨が降らぬ確信を持ってから、昨夜寝る前にベランダにカメラをセットしておいた。朝早く起きるより楽だからだ。夜のうちに1000枚くらい写真が撮れてしまうが、SDカードには余裕があるので大丈夫である。

 昼間は用事があるのでカメラの面倒は見れないが、放置しておけば淡々と写真は撮れていく。

IMG_3143

 で、撮れた写真をWindows Movie Makerに流し込むと、微速撮影動画の一丁上がりだ。

 スケッチは次のとおりである。

//
//  camera2Web.ino
//    27.07.20(月) 0850~
//    佐藤俊夫
//    Adafruit製小型TTLシリアルJPEGカメラ+ETHERNET SHIELD 2で
//    間欠撮影をし、Webでダウンロードできるようにする。
//
#include <Adafruit_VC0706.h>
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include <Ethernet2.h>

#define CHIPSELECT 4

SoftwareSerial CAMCONNECTION(2, 3);
Adafruit_VC0706 CAM = Adafruit_VC0706(&CAMCONNECTION);
const unsigned long int INTERVAL = 30L * 1000L;
byte MAC[] = {  0x90, 0xA2, 0xDA, 0x0F, 0xF6, 0x74 };
IPAddress IP(192, 168, 1, 129);
EthernetServer SERVER(80);
EthernetClient CLIENT;

void setup() {
  pinMode(10, OUTPUT);
  if(!SD.begin(CHIPSELECT)) return;
  if(!CAM.begin()) return;
  CAM.setImageSize(VC0706_320x240);
  Ethernet.begin(MAC, IP);
  SERVER.begin();
  delay(1000);
}

void loop() {
  static unsigned long int prevtime = 0;
  char c;
  String rstr = "";
  //  INTERVALおきに写真を撮る
  if(millis() >= prevtime + INTERVAL){
    prevtime = millis();
    takePicture();
  }
  //  Webサーバ
  CLIENT = SERVER.available();
  if(CLIENT) {
    while(CLIENT.connected()) {
      if(CLIENT.available()) {
        c = CLIENT.read();
        rstr += c;
        if(rstr.endsWith("\r\n")){
          break;
        }
      }
    }
    if(rstr.indexOf("IMG") >= 0){
      String filename = "DCIM/";
      char cfilename[17];
      filename.concat(rstr.substring(rstr.indexOf("IMG"), rstr.indexOf("JPG") + 3));
      filename.toCharArray(cfilename, 17);
      CLIENT.println("HTTP/1.1 200 OK");
      CLIENT.println("Content-Type: image/jpg");
      CLIENT.println("Connection: close");
      CLIENT.println();
      File img = SD.open(cfilename);
      while(img.available()){
        CLIENT.write(img.read());
      }
      img.close();
    }else{
      sendform();
    }
    rstr = "";
    delay(1);
    // close the connection:
    CLIENT.stop();
  }
  delay(20);
}

void sendform(){
  //  フォームを送る。
  CLIENT.println("HTTP/1.1 200 OK");
  CLIENT.println("Content-Type: text/html");
  CLIENT.println("Connection: close");
  CLIENT.println();
  CLIENT.println("<!DOCTYPE HTML>");
  CLIENT.println("<html><head></head><body><center>");
  File dcim = SD.open("/DCIM");
  while(true) {
    File imgfile =  dcim.openNextFile();
    if(!imgfile){
      dcim.rewindDirectory();
      break;
    }
    CLIENT.write("<a href=\"");
    CLIENT.write(imgfile.name());
    CLIENT.write("\">");    
    CLIENT.write(imgfile.name());
    CLIENT.println("</a><br>");
    imgfile.close();    
  }
  dcim.close();
  CLIENT.println("</center></body></html>");
}

void takePicture(){
  static unsigned int pnum = 0;
  char filename[] = "DCIM/img0000.jpg";
  while(!CAM.takePicture());
  do{
    filename[8]  = '0' + pnum / 1000;
    filename[9]  = '0' + (pnum / 100) % 10;
    filename[10] = '0' + (pnum /  10) % 10;
    filename[11] = '0' + pnum % 10;
    pnum ++;
  }while(SD.exists(filename));
  if(pnum > 9999) pnum = 0;
  File imgFile = SD.open(filename, FILE_WRITE);
  uint16_t jpglen = CAM.frameLength();
  pinMode(8, OUTPUT);
  while (jpglen > 0) {
    uint8_t *buffer;
    uint8_t bytesToRead = min(32, jpglen);
    buffer = CAM.readPicture(bytesToRead);
    imgFile.write(buffer, bytesToRead);
    jpglen -= bytesToRead;
  }
  while(!CAM.reset());
  imgFile.close();
}