Picoを使用したハードウェアブート選択スイッチ
スイッチを切り替えてコンピュータの電源を入れる前でも、起動するOSを事前に選択してください。これで、OSを選択するのを待つ必要はありません。
ストーリー
プロジェクトのHackaday.ioをさまよいながら、Stephen Holdawayによるこのプロジェクト(クリック)に出くわしました。このプロジェクトでは、彼はすべてのデュアルブートユーザーが直面する苛立たしいタスクを解決しました。このタスクは、ウィンドウに切り替えたいときにいつでもGRUBメニューからos(Windows)を選択するのを待っています。彼はハードウェアスイッチを追加して、コンピューターの電源を入れるたびに起動するOSを決定することができました。
彼は、STM32マイクロコントローラーをUSB大容量ストレージデバイスとして構成することでこれを実現しました。彼は、ハッカデイの投稿(クリック)で、プロジェクトの調査と実装の全過程を記録しています。実装をよりよく理解するために彼の投稿を読んでください。
このプロジェクトでは、変更をRaspberry PiPicoに移植する方法を紹介します。私のバージョンは、このGitHubリポジトリにあります(クリック)。
GNU GRUBは、オペレーティングシステムがロードされる前に実行されるプログラムです。このメニューから、ロードするOSを選択できます。 GRUBは、使用できるモジュールが非常に限られています。これは、USB経由で接続されたマイクロコントローラーからデータを読み取ることができないことを意味します。ただし、ストレージディスクからデータを読み取ることはできます。
そのため、マイクロコントローラーを大容量記憶装置として列挙することで、GRUBをだましてマイクロコントローラーからデータを読み取ることができます。
したがって、ファイル switch.cfg を持つtinyUSBライブラリを介して、ラズベリーパイピコを大容量記憶装置として列挙します。 ファイル。picoがスイッチの位置を書き込みます。つまり、 ONの場合は1、OFFの場合は0 。
GRUBにスクリプトを追加する必要があります。このスクリプトは、switch.cfgファイルを読み取り、デフォルトを設定するための関数です。 〜 0(Ubuntu)/ 2(Windows)。
GRUBは、読み込み時にカスタムスクリプトを実行し、UUID識別子でデバイスを検索し、終了する場合はswitch.cfgファイルを読み取ります。スイッチの位置を取得した後、デフォルトのOS選択をそれぞれ設定します。
要約すると、
- picoはそれ自体を大容量記憶装置として構成します。
- grubメニューはスクリプトを呼び出し、特定のファイルを要求します。
- Picoは、switch.cfgファイルにスイッチの位置を追加することで読み取り要求に応答します。
- grubのスクリプトはファイルから情報を抽出し、抽出されたデータからデフォルトのオプションを設定します。
Picoをマスストレージデバイスとして構成する
cdc_msc を使用しました これを達成するためのtinyUSBによる例。この例では、picoを大容量記憶装置として構成し、FAT12ファイルシステムを作成して、README.txtファイルを列挙します。
README.txtをswitch.cfgに変更し、「set os_hw_switch =0 \ n」という行をファイルに追加しました。
#define SWITCH_CFG_CONTENTS \
"set os_hw_switch =0 \ n"
...
// ----- --------ブロック3:Readmeコンテンツ------------- //
SWITCH_CFG_CONTENTS
これで、picoを大容量記憶装置として構成しました。 uf2ファイルをpicoにコピーした後、ストレージデバイスとして列挙します。 GRUBスクリプトのデバイスのUUIDID( UUID =” 00001234”)が必要になります。
$ sudo blkid
...
/ dev / sda:SEC_TYPE ="msdos" LABEL_FATBOOT ="TinyUSB MSC" LABEL ="TinyUSB MSC" UUID ="0000-1234" BLOCK_SIZE ="512" TYPE ="vfat"
次に、スイッチの位置を読み取り、それに応じてswitch.cfgファイルの内容を変更する必要があります。つまり
- スイッチがオンの場合: set os_hw_switch =1 \ n
- スイッチがオフの場合: set os_hw_switch =0 \ n
プルダウンするように設定されているスイッチピンとしてGPIO_PIN28を使用しました。
read_switch_value スイッチの位置を戻します。つまり、「1」がオン(ハイにプル)で、「0」がオフ(ローにプル)です。
// ------------------------- main.c -------- -------------
#define SWITCH_PIN 28
//スイッチ値の読み取り
uint8_t read_switch_value()
{
gpio_get(SWITCH_PIN)を返しますか? '1': '0';
}
int main(void)
{
gpio_init(SWITCH_PIN);
// PINをINPUTとして構成します
gpio_set_dir(SWITCH_PIN、false);
//ピンをPULL_DOWNとして構成します
gpio_set_pulls(SWITCH_PIN、false、true);
switch.cfgにスイッチの位置を書き込むために、 readGRUBConfig()を使用しました read_switch_value を呼び出します 機能し、スイッチ位置で出力バッファを設定します。
3番目のブロックを読んだときに3 lba は3に設定されているため、呼び出しをインターセプトして readGrubConfig ファイルの内容がコピーされるバッファを渡します。
// ------------------------- msc_disk.c -------- -------------
static char grubConfigStr [] ="set os_hw_switch =0 \ n";
static void readGrubConfig(uint8_t * output)
{
//現在のスイッチ値で構成文字列を変更します
grubConfigStr [sizeof(grubConfigStr)-3] =read_switch_value();
memcpy(output、&grubConfigStr、sizeof(grubConfigStr));
}
// READ10コマンドを受信するとコールバックが呼び出されます。
//ディスクのデータをバッファにコピーし(最大bufsize)、コピーされたバイト数を返します。
int32_t tud_msc_read10_cb(uint8_t lun、uint32_t lba、uint32_t offset、void * buffer、uint32_t bufsize)
{
(void)lun;
//ファイルを読み取るとき
if(lba ==3){
readGrubConfig(buffer);
return bufsize;
}
...
...
}
Picoコードをコンパイルします
pico stdlib を追加する必要があります gpio を取得するためのコード ピンアクセス。
// ------------------------- main.c -------- ---------------------------
#include
#include
#include
#include "bsp / board.h"
#include "tusb.h"
...
#include "pico / stdlib.h "
プロジェクトを作成するには:
$ mkdir build
$ cd build
$ cmake ..
$ make
これらの変更をUbuntu20.10に追加しました。
$ sudo vim /etc/grub.d/40_custom
....
#ハードコードされたハードウェアスイッチデバイスを探しますファイルシステムID
search --no-floppy --fs-uuid --set hdswitch 0000-1234
#見つかった場合は、動的構成ファイルを読み取り、各位置に適切なエントリを選択します
if ["$ {hdswitch}"]; then
source($ hdswitch)/switch.cfg
if ["$ {os_hw_switch}" ==0]; then
#Linuxを起動
set default ="0"
elif ["$ {os_hw_switch}" ==1]; then
#Windowsを起動します
set default ="2"
else
#デフォルトにフォールバックします
set default ="$ {GRUB_DEFAULT}"
fi
else
set default ="$ {GRUB_DEFAULT}"
fi
まず、ファイルシステムを検索します。 GRUBにはサブコマンド search があります このためだけに。
- -フロッピーなし オプションはフロッピーデバイスの検索を防ぎます
- -fs–uuid 0000-1234 UUIDが0000〜1234のファイルシステムを検索します。
デバイスが見つかった場合、最初に見つかったデバイスが環境変数の値として設定されます。
–hdswitchを設定 hdswitch は環境変数であり、見つかった場合はディスク名で設定されます。
次に、 hdswitch の場合、switch.cfgファイルをソースします 変数が設定され、別の環境変数が作成されます os_hw_switch
スイッチの位置、つまり0/1のいずれかを使用します。
os_hw_switch の値を読み取ります
デフォルトをそれぞれ0または2に設定します。 GRUBメニューでUbuntuが0番目の位置にあり、Windowsが2番目の位置にあるため0。
最後に、 hdswitch が設定されていなかったため、デフォルトを GRUB_DEFAULT。に設定しました。
次に、grubを更新する必要があります:
$ sudo update-grub
出典: Picoを使用したハードウェアブート選択スイッチ
製造プロセス