- 投稿日:2020-09-13T19:37:29+09:00
【Ubuntu Dell XPS13-9380】Firmware(UEFI/BIOS)の更新が出来なくて困ったけどfwupdを使って更新できた話
0. はじめに
こんにちは。都内でエンジニアをしている、@gkzvoiceです。
先日、私用Linux PCのFirmwareの更新でコケてしまったので、そのトラブルシュートにチャレンジしておりました。あれ?firmwareの更新に失敗したかも
— GakujiTamaki@July Tech Festa運営スタッフ/ #bosyu芸人 (@gkzvoice) September 8, 2020結論からお伝えしますと、後述する、fwupdを使って無事更新することができました。
そこで本記事では、fwupdを使ってFirmware(UEFI/BIOS)の更新ができるようになるまでの手順について解説していきます。1. 目次
- 2. 環境/バージョン情報
- 3. 遭遇したエラーの説明
- 4. 更新手順
- 5. 参考資料
2.環境/バージョン情報
ローカル開発環境
- Dell XPS13-9380
- Ubuntu 20.04.1 LTS (Focal Fossa)"
- BIOS 1.11.0
- fwupdmgr
- client 1.3.11
- daemon 1.3.11
僕だけかも知れませんが、バージョン一つ確認するのも苦労したので確認に使ったコマンドを貼っておきます(とくにBIOS。。)。
## Dell XPS13-9380 $ sudo lshw -short | head -3 H/W path Device Class Description ============================================================== system XPS 13 9380 (08AF) ## Ubuntu $ cat /etc/os-release NAME="Ubuntu" VERSION="20.04.1 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.1 LTS" VERSION_ID="20.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=focal UBUNTU_CODENAME=focal ## BIOS $ sudo dmidecode -s bios-version 1.11.0 ## fwupdmgr client/daemon $ fwupdmgr --version client version: 1.3.11 compile-time dependency versions gusb: 0.3.4 efivar: 37 daemon version: 1.3.113. 遭遇したエラーの説明
なにがきっかけかは分かりませんが、下記のスクリーンショットの左側に表示されているようなエラーメッセージが画面に出るようになったんですよね大汗。
エラーメッセージ全文です↓。
Unable to update "Dell Inc. System Firmware" as download failed: failed to download https://fwupd.org/downloads/-xxxxxxx-d35-XPS_9380_1.11.0.cab: Connection terminated unexpectedlly4. 更新手順
4-1.下記のLinux Vendor Firmware Service(LVFS)から自分PCに合ったcabをダウンロード
- 僕の場合は「2.環境/バージョン情報」で先述したとおり、XPS13-9380のcab
https://fwupd.org/lvfs/devices/com.dell.uefice945437.firmware
- 下記のようにcurlやwgetを使ってダウンロードしても、GUIでcabをクリックしてもよい
$ curl https://fwupd.org/downloads/60344cbcc1f3c061ea202e1c7d7cc9c6333f0f070eba09fc8ef27114fe3ced35-XPS_9380_1.11.0.cab \ > --output $HOME/Downloads/xps_9380.cab % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 21.6M 100 21.6M 0 0 1454k 0 0:00:15 0:00:15 --:--:-- 2711k
- 無事 curlのoutputオプションで指定したダウンロード先にcabがあることを確認(GUIでダウンロードされた方はよしなに)
$ ls $HOME/xps_9380.cab $HOME/Downloads/xps_9380.cab4-2. fwupdmgr installコマンドでcabをインストール
- 下記のように
fwupdmgr install /path/to/$FILE
を実行してからy
を押すfwupdmgr install
コマンドを実行するためには、ACアダプタをつなぐ必要があります。- なお、この
fwupdmgr install
とはfwupdというデーモンが提供するインストールコマンドみたいです。$ fwupdmgr install Downloads/xps_9380.cab Decompressing… [***************************************] Authenticating… [***************************************] Installing on System Firmware… ] Scheduling… [***************************************] Successfully installed firmware An update requires a reboot to complete. Restart now? [y|N]:
- 後は画面に従って
再起動
したり、淡々と進めるだけでした。※
fwupdmgr install
コマンドについては、fwupd/firmware-dellリポジトリ
で自分で立てたissueで教えていただきました。
Unable to update "Dell Inc. System Firmware" as download failed · Issue #35 · fwupd/firmware-dell
fwupdmgr install
コマンドの解説についてはこちらをご参照ください。Download the .cab files that match your hardware and then install them on the target hardware via Ansible or Puppet using
fwupdmgr install foo.cab.
参考:Offline Firmware — LVFS documentation
- fwupdについてはこちらを。
The Linux Foundationは3月26日(米国時間),同ファウンデーション傘下の新しいプロジェクトとして「Linux Vendor Firmware Service(LVFS)」がスタート
したことを発表した。Linux Vendor Firmware Service
LVFS Project Announcement - The Linux Foundation
LVFSはRed Hatの開発者が中心となって進めてきた活動で,各ハードウェアベンダが提供するファームウェアやBIOSを,再配布可能な形式(.cab)でサイト上で集約し,ユーザや開発者は「fwupd」というデーモンを介してLVFSに接続することで,ローカルマシンのファームウェアアップデートが可能
になる。5. 参考資料
- Unable to update "Dell Inc. System Firmware" as download failed · Issue #35 · fwupd/firmware-dell
- Offline Firmware — LVFS documentation
- 2019年3月29日 ファームウェア提供のスタンダードに! Linux Foundationの新プロジェクト「Linux Vendor Firmware Service」がスタート
P.S. Twitterもやってるのでフォローしていただけると泣いて喜びます:)
- 投稿日:2020-09-13T16:44:22+09:00
ファイル作成時に名前が重複したら番号をつけるシェルスクリプト
スクリプト概要
- 引数で指定したファイル名の空ファイル作成
- すでに同名のファイルが存在すれば番号をつけて作成
- 番号がついたファイルも存在していればその番号より一つ大きい番号をつけて作成
#!/bin/bash file=$1 if [[ -e ${file} ]]; then maxnumber=$(find . -mindepth 1 -maxdepth 1 -printf "%f\n" \ | grep -e "^${file}\$" -e "^${file}_[0-9][0-9]*\$" \ | sed "s/^${file}_\\{0,1\\}//" \ | sed 's/^$/0/' \ | sort -rn \ | head -n 1 ) ; file+="_$((maxnumber+1))" fi touch $file解説
# findでカレントディレクトリ(.)のファイル一覧を検索 find . -mindepth 1 -maxdepth 1 -printf "%f\n" # -mindepth 1と -maxdepth 1 で検索する階層をカレントのみに限定 # -printf でディレクトリ名を除いたファイル名だけを出力 (%f)し改行で区切る(\n)# grep で番号なしファイルと番号ありファイルを検索 grep -e "^${file}\$" -e "^${file}_[0-9][0-9]*\$" # -e オプションで正規表現を使用# 「ファイル名_番号」 の内「ファイル名_」を除いて番号のみを出力 sed "s/^${file}_\\{0,1\\}//" # {0,1}は直前の文字の0から1回以下の繰り返しを表すため、_があってもなくてもマッチする # その際{}はエスケープ(\)が必要。\自体にもエスケープが必要なので\\となる# 番号のついていないファイルは空行となるので0に置換 sed 's/^$/0/' # ^は後に続く文字が行頭一致、$は直前の文字列が行末一致を指す # ^$は間には何も書かれていないので空行を指す# 数字の大きい順に並べ替え sort -rn # -r 逆順に並べ替えるオプション # -n 文字列を数値とみなすオプション# 一番大きい数字のみを出力 head -n 1 # -n 1 先頭の1行のみ出力ここまでのコマンドで重複するファイル名の一番大きい数字を取得できた。
これらのコマンドをコマンド置換$()で囲むことで実行結果を変数maxnumberに代入している。ここから新たに番号をつけてファイルを作成していく。
# ファイル名に 「_番号」を付与 file+="_$((maxnumber+1))" # maxnumberに1を足してファイル名に「_番号」を追加# ファイル作成 touch ${file}ファイル名が重複していない場合は番号なしでそのまま作成されます。
- 投稿日:2020-09-13T16:20:43+09:00
LicheePi NanoでUSBデバイスを認識させる
LicheePi NanoのUSB
載っているSoCのF1C100sはUSB OTGを1ポート備えている。
しかし2020/09/13時点のLicheePi githubのnano-5.2-tfブランチではUSBデバイスを認識できない。Patch
WhyCan Forumのf1c100s linux 5.2 USB已完美驱动,host+device完美运行というスレッドでパッチが公開されている。
百度网盘にパッチをあてたソースが置いてあるようだけどBaiduのアカウントを持っていないため未確認以下、diffの引用
base: 39402432e (grafted, HEAD -> nano-5.2-tf, origin/nano-5.2-tf) HEAD@{0}: clone: from https://github.com/Lichee-Pi/linux.git diff: modified: arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts modified: arch/arm/boot/dts/suniv-f1c100s.dtsi modified: drivers/phy/allwinner/phy-sun4i-usb.c modified: drivers/usb/musb/sunxi.c diff --git a/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts b/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts index ca644541a..890a57717 100644 --- a/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts +++ b/arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts @@ -20,7 +20,7 @@ }; panel: panel { - compatible = "lg,lb070wv8", "simple-panel"; + compatible = "qiaodian,qd43003c0-40", "simple-panel"; #address-cells = <1>; #size-cells = <0>; enable-gpios = <&pio 4 6 GPIO_ACTIVE_HIGH>; @@ -79,3 +79,17 @@ pinctrl-0 = <&uart0_pe_pins>; status = "okay"; }; + +&otg_sram { + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + usb0_id_det-gpio = <&pio 4 2 GPIO_ACTIVE_HIGH>; /* PE2 */ + status = "okay"; +}; diff --git a/arch/arm/boot/dts/suniv-f1c100s.dtsi b/arch/arm/boot/dts/suniv-f1c100s.dtsi index 26d8e5577..437bdf7d9 100644 --- a/arch/arm/boot/dts/suniv-f1c100s.dtsi +++ b/arch/arm/boot/dts/suniv-f1c100s.dtsi @@ -221,6 +221,31 @@ resets = <&ccu RST_BUS_UART2>; status = "disabled"; }; + usb_otg: usb@1c13000 { + compatible = "allwinner,suniv-musb"; + reg = <0x01c13000 0x0400>; + clocks = <&ccu CLK_BUS_OTG>; + resets = <&ccu RST_BUS_OTG>; + interrupts = <26>; + interrupt-names = "mc"; + phys = <&usbphy 0>; + phy-names = "usb"; + extcon = <&usbphy 0>; + allwinner,sram = <&otg_sram 1>; + status = "disabled"; + }; + + usbphy: phy@1c13400 { + compatible = "allwinner,suniv-usb-phy"; + reg = <0x01c13400 0x10>; + reg-names = "phy_ctrl"; + clocks = <&ccu CLK_USB_PHY0>; + clock-names = "usb0_phy"; + resets = <&ccu RST_USB_PHY0>; + reset-names = "usb0_reset"; + #phy-cells = <1>; + status = "disabled"; + }; fe0: display-frontend@1e00000 { compatible = "allwinner,suniv-f1c100s-display-frontend"; reg = <0x01e00000 0x20000>; diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 856927382..3cd9e946a 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -98,6 +98,7 @@ #define POLL_TIME msecs_to_jiffies(250) enum sun4i_usb_phy_type { + suniv_phy, sun4i_a10_phy, sun6i_a31_phy, sun8i_a33_phy, @@ -859,6 +860,14 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) return 0; } +static const struct sun4i_usb_phy_cfg suniv_cfg = { + .num_phys = 1, + .type = suniv_phy, + .disc_thresh = 3, + .phyctl_offset = REG_PHYCTL_A10, + .dedicated_clocks = true, +}; + static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { .num_phys = 3, .type = sun4i_a10_phy, @@ -973,6 +982,7 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = { }; static const struct of_device_id sun4i_usb_phy_of_match[] = { + { .compatible = "allwinner,suniv-usb-phy", .data = &suniv_cfg }, { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg }, { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg }, { .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg }, diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index 832a41f9e..83f3fa5b0 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c @@ -714,14 +714,17 @@ static int sunxi_musb_probe(struct platform_device *pdev) INIT_WORK(&glue->work, sunxi_musb_work); glue->host_nb.notifier_call = sunxi_musb_host_notifier; - if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb")) + if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb") || + of_device_is_compatible(np, "allwinner,suniv-musb")) { set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags); + } if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb")) set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags); if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb") || - of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) { + of_device_is_compatible(np, "allwinner,sun8i-h3-musb") || + of_device_is_compatible(np, "allwinner,suniv-musb")) { set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags); set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags); } @@ -812,6 +815,7 @@ static int sunxi_musb_remove(struct platform_device *pdev) } static const struct of_device_id sunxi_musb_match[] = { + { .compatible = "allwinner,suniv-musb", }, { .compatible = "allwinner,sun4i-a10-musb", }, { .compatible = "allwinner,sun6i-a31-musb", }, { .compatible = "allwinner,sun8i-a33-musb", },上記のように
suniv-f1c100s-licheepi-nano.dts
suniv-f1c100s.dtsi
phy-sun4i-usb.c
sunxi.c
を修正してビルドすればUSBデバイスを認識するようになる
- 投稿日:2020-09-13T13:49:13+09:00
ubuntu18.04 で X11 を使う (C言語)
X11ライブラリのインストール
sudo apt update (sudo apt upgrade) sudo apt install libx11-dev#include <X11/Xlib.h> //Xlibに必要なインクルード #include <X11/Xutil.h>
Xlibに必要なライブラリの配置を確認する。
ヘッダファイルと共有ライブラリの配置の確認。sudo find /usr -type f -name Xlib.h sudo find /usr -type f -name libX11.soその他コンパイルオプションをそろえたコマンド
gcc -o xlib_test xlib_test.c -O2 -I/usr/include -L/usr/lib/x86_64-linux-gnu -lX11 -lm真っ黒なウィンドウを表示するだけのテストプログラム
http://cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/XLIB/xlib2.html
上記のサイトのプログラムをそのまま試しました。// reference URL // http://cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/XLIB/xlib2.html #include <X11/Xlib.h> //Xlibに必要なインクルード #include <X11/Xutil.h> #include <stdio.h> int main( void ) { Display* dis; //Display pointer Window win; //Window ID XSetWindowAttributes att; //窓属性の変数 XEvent ev; //イベント取り込み変数 dis = XOpenDisplay( NULL ); //Xserverとの接続 win = XCreateSimpleWindow( dis, RootWindow(dis,0), 100, 100, 256, 256, 3, WhitePixel(dis,0), BlackPixel(dis,0) ); //窓の生成 att.backing_store = WhenMapped; //絵を保存する設定をする XChangeWindowAttributes( dis, win, CWBackingStore, &att ); XMapWindow( dis, win ); //窓の表示 XFlush( dis ); //リクエストの強制送信 XSelectInput( dis, win, ExposureMask ); do{ //窓が開くの待つループ XNextEvent( dis, &ev); }while( ev.type != Expose ); // Exposeイベントが届くまでここを繰り返す // ここまで来たら真っ黒な窓が登場しているはず。 getchar(); // リターンキーが押されるまで待つ。 XDestroyWindow( dis, win ); //窓の消去 XCloseDisplay( dis ); //Xserverと断線 return 0; }
Makefile
を作成することでコンパイルを楽にする。CC = gcc CFLAGS = -O2 -I/usr/include LIBS = -L/usr/lib/x86_64-linux-gnu -lX11 -lm TARGET = xlib_test SRC = xlib_test.c $(TARGET): $(SRC) $(CC) -o $@ $^ $(CFLAGS) $(LIBS) clean: rm $(TARGET)
$@
はターゲットファイル。
$^
は素材指定しているファイル。
- 投稿日:2020-09-13T11:26:41+09:00
Gatsbyのdevelopコマンドした際、「Something is already running at port 8000」と出たときの対処
環境
・OS: macOS 10.15.5
・gatsby: 2.24.14事例
何の気なしに「gatsby develop」を実行すると、次のメッセージが表示する。
Something is already running at port 8000 ? Would you like to run the app at another port instead? › (Y/n)Yを選ぶと、port 8001で起動する。
nを選ぶとサーバーを起動せずに終了する。対応
8000ポートで使われているプロセスをkillする。
①まずはポートのプロセスを調べる
lsof -i :8000結果は次の通り。
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME node 14778 saku 27u IPv4 0xb6bc7a92d19432ab 0t0 TCP localhost:irdmi (LISTEN)②プロセスをkillする
kill -9 [PIDの数字]こーゆーのをさらっと解消できるといいんですが、まだまだです。
- 投稿日:2020-09-13T00:10:52+09:00
プロンプトに表示するパスを簡略化する
/home/username/foo/barは長い
fishみたいに
~/f/bar
でプロンプトに表示させたいfishのソースを見る
string replace -ar '(\.?[^/]{'"$fish_prompt_pwd_dir_length"'})[^/]*/' '$1/' $tmpとなっている。
string replace
はfishの関数なのでbashでこれを再現する。function abbr_pwd() { local p=$(echo $PWD | sed "s@$HOME@~@") local directories=(${p//\// }) local _n_d=${#directories[@]} local _last=${directories[_n_d - 1]} local _abbr_pwd="" if [ ${directories[0]} != "~" ]; then _abbr_pwd=$_abbr_pwd/ fi # 本当はif [[ $p =~ (.?[^\/]{1})[^\/]*\/ ]]で処理したい for d in "${directories[@]:0:_n_d-1}"; do _abbr_pwd=$_abbr_pwd${d:0:1}/ done echo $_abbr_pwd$_last }fishのコードのように正規表現で処理をしたいが、
if [[ $p =~ (.?[^\/]{1})[^\/]*\/ ]]; then; echo ${BASH_REMATCH[@]};fi
では最初のマッチ~
のみしか得られなかった。(ちゃんと調べればやりようはありそう)ディレクトリのパス
/home/username/foo/bar
を~/foo/bar
にするためsed
で置換をし、
"/"
で文字列を分解、最後の以外の部分を先頭文字だけ残して"/"で結合、最後にbarを足すことで~/f/bar
を得た。
$HOME
より根のパスでは/usr/share/theme
->/u/s/theme
のように/
が先頭に来るようにした。ただし、自ユーザ以外のホームディレクトリ下($HOMEで置換ができない)だと
/h/o(otherUser)/f/bar
みたいに冗長になる。PROMPTに表示する
PS1='[\u@\h] $(abbr_pwd $PWD) \$ 'みたいに適宜いじってください。