Hardware Boot Select Switch mit Pico
Wählen Sie das zu bootende Betriebssystem bereits vor dem Einschalten des Computers durch Umschalten eines Schalters aus. Jetzt müssen Sie nicht mehr warten, um das Betriebssystem auszuwählen.
Geschichte
Auf Hackaday.io für Projekte bin ich über dieses Projekt (klick) von Stephen Holdaway gestolpert. In diesem Projekt hat er eine frustrierende Aufgabe gelöst, mit der jeder Dual-Boot-Benutzer konfrontiert ist, der sitzt und darauf wartet, os (Windows) aus dem GRUB-Menü auszuwählen, wenn wir zu Windows wechseln möchten. Er konnte einen Hardwareschalter hinzufügen, um das Betriebssystem zu bestimmen, das jedes Mal gestartet werden soll, wenn der Computer eingeschaltet wird.
Er erreichte dies, indem er den STM32-Mikrocontroller als USB-Massenspeichergerät konfigurierte. Seine gesamte Reise durch die Forschung und Umsetzung des Projekts hat er in Hackaday post(click) dokumentiert. Bitte gehen Sie seinen Beitrag durch, um die Implementierungen besser zu verstehen.
In diesem Projekt zeige ich, wie es mir gelungen ist, die Änderungen auf Raspberry Pi Pico zu portieren. Sie finden meine Version in diesem GitHub-Repository (Klicken).
Konzept
GNU GRUB ist ein Programm, das ausgeführt wird, bevor ein Betriebssystem geladen wird. Über dieses Menü können wir auswählen, welches Betriebssystem geladen werden soll. GRUB bietet nur sehr begrenzte Module zum Arbeiten. Dies bedeutet, dass es keine Daten von einem über USB angeschlossenen Mikrocontroller lesen kann. Aber es kann Daten von Speicherdisketten lesen.
So können wir GRUB dazu bringen, Daten vom Mikrocontroller zu lesen, indem wir unser Mikro als Massenspeichergerät aufzählen.
Daher zählen wir unseren Himbeer-Pi-Pico als Massenspeichergerät über eine winzige USB-Bibliothek auf, die eine Datei switch.cfg haben wird Datei, in die Pico die Schalterposition schreibt, d. h. 1 für EIN 0 für AUS .
Wir müssen ein Skript in GRUB hinzufügen, das sind Funktionen zum Lesen der switch.cfg-Datei und zum Festlegen der Standardeinstellung zu 0(Ubuntu)/2(Windows).
GRUB führt beim Laden unsere benutzerdefinierten Skripts aus, die wiederum anhand ihrer UUID-Kennungen nach unserem Gerät suchen und beim Beenden die Datei switch.cfg lesen. Nachdem Sie die Schalterposition erhalten haben, wird die Standard-OS-Auswahl entsprechend festgelegt.
Zusammenfassend:
- pico konfiguriert sich selbst als Massenspeichergerät.
- Grub-Menü ruft unser Skript auf und fragt nach der jeweiligen Datei.
- Pico antwortet auf die Leseanfrage, indem es die Schalterposition in der Datei "switch.cfg" hinzufügt.
- Das Skript in Grub extrahiert die Informationen aus der Datei und legt die Standardoption aus den extrahierten Daten fest.
Konfigurieren von Pico als Massenspeichergerät
Ich habe die cdc_msc . verwendet Beispiel von tinyUSB, um dies zu erreichen. Im Beispiel wird der Pico als Massenspeichergerät konfiguriert, ein FAT12-Dateisystem erstellt und eine README.txt-Datei aufgelistet.
Ich habe die README.txt in switch.cfg geändert und der Datei die Zeile „set os_hw_switch=0\n“ hinzugefügt.
#define SWITCH_CFG_CONTENTS \
"set os_hw_switch=0\n"
...
//----- -------- Block3:Readme-Inhalt -------------//
SWITCH_CFG_CONTENTS
Jetzt haben wir pico als Massenspeichergerät konfiguriert. Nach dem Kopieren der uf2-Datei nach Pico wird sie als Speichergerät aufgezählt. Wir benötigen die UUID-ID des Geräts für das GRUB-Skript, das heißt UUID=“0000-1234″.
$ sudo blkid
...
/dev/sda:SEC_TYPE="msdos" LABEL_FATBOOT="TinyUSB MSC" LABEL="TinyUSB MSC" UUID="0000-1234" BLOCK_SIZE="512" TYPE="vfat"
Schaltung
Schalterposition lesen und in Datei schreiben
Jetzt müssen wir die Schalterposition lesen und den Inhalt der Datei switch.cfg entsprechend ändern, d. h.
- wenn der Schalter eingeschaltet ist: os_hw_switch=1\n
- wenn der Schalter AUS ist: set os_hw_switch=0\n
Ich habe GPIO_PIN 28 als Schaltstift verwendet, der auf Herunterziehen eingestellt ist.
read_switch_value Bringen Sie die Schalterposition zurück, d. h. „1“ ist eingeschaltet (hoch gezogen) und „0“ ist ausgeschaltet (tief gezogen).
//-------------------------main.c-------- -------------
#define SWITCH_PIN 28
// Schalterwert lesen
uint8_t read_switch_value()
{
gpio_get(SWITCH_PIN) zurückgeben? '1' :'0';
}
int main(void)
{
gpio_init(SWITCH_PIN);
// Pin als INPUT konfigurieren
gpio_set_dir(SWITCH_PIN, false);
//Pin als PULL_DOWN konfigurieren
gpio_set_pulls (SWITCH_PIN,false,true);
Um die Schalterposition in die switch.cfg zu schreiben, habe ich readGRUBConfig() . verwendet was den read_switch_value . aufruft Funktion und stellen Sie den Ausgangspuffer mit der Schalterstellung ein.
Ich fand das beim Lesen des dritten Blocks3 lba ist auf 3 gesetzt, daher wird der Anruf abgefangen und readGrubConfig calling aufgerufen und Übergeben des Puffers, in den der Inhalt der Datei kopiert wird.
//-------------------------msc_disk.c-------- -------------
static char grubConfigStr[] ="set os_hw_switch=0\n";
static void readGrubConfig(uint8_t* output)
{
// Konfigurationsstring mit aktuellem Schalterwert ändern
grubConfigStr[sizeof(grubConfigStr)-3] =read_switch_value();
memcpy(output, &grubConfigStr, sizeof(grubConfigStr));
}
// Callback wird aufgerufen, wenn ein READ10-Befehl empfangen wird.
// Kopieren Sie die Daten der Festplatte in den Puffer (bis zu Bufsize) und geben Sie die Anzahl der kopierten Bytes zurück.
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
{
(void) lun;
// beim Lesen der Datei
if(lba ==3){
readGrubConfig(buffer);
bufsize zurückgeben;
}
...
...
}
Kompilieren Sie den Pico-Code
Wir müssen pico stdlib . hinzufügen zu unserem Code, um das gpio zu erhalten PIN-Zugriff.
//-------------------------main.c-------- ----------------------------------------
#include
#include
#include
#include "bsp/board.h"
#include "tusb.h"
...
#include "pico/ stdlib.h"
Um das Projekt zu machen:
$ mkdir build
$ cd build
$ cmake ..
$ make
GRUB konfigurieren, um den Dateiinhalt zu lesen
Ich habe diese Änderungen in meinem Ubuntu 20.10 hinzugefügt.
$ sudo vim /etc/grub.d/40_custom
....
# Suchen Sie das Hardware-Switch-Gerät anhand seiner hartcodierten Dateisystem-ID
search --no-floppy --fs-uuid --set hdswitch 0000-1234
# Falls gefunden, dynamische Konfigurationsdatei lesen und für jede Position den passenden Eintrag auswählen
if [ "${hdswitch}" ]; then
source ($hdswitch)/switch.cfg
if [ "${os_hw_switch}" ==0 ]; then
# Linux booten
set default="0"
elif [ "${os_hw_switch}" ==1 ]; then
# Booten von Windows
set default="2"
else
# Fallback to default
set default="${GRUB_DEFAULT}"
fi
sonst
set default="${GRUB_DEFAULT}"
fi
Zuerst suchen wir nach unserem Dateisystem. GRUB hat einen Unterbefehl suchen nur dafür.
- -no-floppy Option verhindert das Durchsuchen von Diskettengeräten
- -fs–uuid 0000-1234 durchsucht ein Dateisystem mit der UUID 0000-1234.
Wenn ein Gerät gefunden wird, wird das erste gefundene Gerät als Wert der Umgebungsvariablen gesetzt.
–hdswitch setzen hdswitch ist unsere Umgebungsvariable und wird mit dem Festplattennamen gesetzt, falls gefunden.
Als Nächstes beziehen wir die Datei switch.cfg, wenn hdswitch Variable festgelegt, wodurch eine weitere Umgebungsvariable os_hw_switch . erstellt wird
mit der Schalterstellung also entweder 0/1.
Wir lesen den Wert des os_hw_switch
und setzen Sie den Standardwert auf 0 bzw. 2. 0, weil Ubuntu an der 0. Position und Windows an der 2. Position im GRUB-Menü ist.
Schließlich, wenn hdswitch nicht festgelegt wurde, setzen wir den Standard auf GRUB_DEFAULT.
Jetzt müssen wir unseren Grub aktualisieren:
$ sudo update-grub
Quelle: Hardware-Boot-Auswahlschalter mit Pico
Herstellungsprozess
- C#-switch-Anweisung
- C# verwenden
- Raspberry Pi 2 Wetterstation
- Temperaturbasiertes Gerätesteuerungssystem mit LM35
- Wetterfernüberwachung mit Raspberry Pi
- SensorTag zu Blynk mit Node-RED
- Bewegungssensor mit Raspberry Pi
- Roboter mit Raspberry Pi und Bridge Shield
- WLAN-gesteuerter Roboter mit Raspberry Pi
- Eine Einführung in das Hacken von eingebetteter IoT-Hardware