20200913のLinuxに関する記事は6件です。

【Ubuntu Dell XPS13-9380】Firmware(UEFI/BIOS)の更新が出来なくて困ったけどfwupdを使って更新できた話

0. はじめに

こんにちは。都内でエンジニアをしている、@gkzvoiceです。
先日、私用Linux PCのFirmwareの更新でコケてしまったので、そのトラブルシュートにチャレンジしておりました。

結論からお伝えしますと、後述する、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.11

3. 遭遇したエラーの説明

なにがきっかけかは分かりませんが、下記のスクリーンショットの左側に表示されているようなエラーメッセージが画面に出るようになったんですよね大汗。

Screenshot from 2020-09-08 22-31-08.png

エラーメッセージ全文です↓。

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 unexpectedlly

4. 更新手順

4-1.下記のLinux Vendor Firmware Service(LVFS⁠)⁠から自分PCに合った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

Screenshot from 2020-09-13 19-49-01.png

  • 無事 curlのoutputオプションで指定したダウンロード先にcabがあることを確認(GUIでダウンロードされた方はよしなに)
$ ls $HOME/xps_9380.cab 
$HOME/Downloads/xps_9380.cab

4-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で教えていただきました。

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に接続することで,ローカルマシンのファームウェアアップデートが可能になる。

参考:2019年3月29日 ファームウェア提供のスタンダードに! Linux Foundationの新プロジェクト「Linux Vendor Firmware Service」がスタート:Linux Daily Topics|gihyo.jp … 技術評論社

5. 参考資料

P.S. Twitterもやってるのでフォローしていただけると泣いて喜びます:)

@gkzvoice

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ファイル作成時に名前が重複したら番号をつけるシェルスクリプト

スクリプト概要

  • 引数で指定したファイル名の空ファイル作成
  • すでに同名のファイルが存在すれば番号をつけて作成
  • 番号がついたファイルも存在していればその番号より一つ大きい番号をつけて作成
#!/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}

ファイル名が重複していない場合は番号なしでそのまま作成されます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LicheePi NanoでUSBデバイスを認識させる

LicheePi NanoのUSB

載っているSoCのF1C100sはUSB OTGを1ポート備えている。
しかし2020/09/13時点のLicheePi githubのnano-5.2-tfブランチではUSBデバイスを認識できない。

Patch

WhyCan Forumf1c100s 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デバイスを認識するようになる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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)

$@はターゲットファイル。
$^は素材指定しているファイル。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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の数字]

こーゆーのをさらっと解消できるといいんですが、まだまだです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プロンプトに表示するパスを簡略化する

/home/username/foo/barは長い

fishみたいに~/f/barでプロンプトに表示させたい

fishのソースを見る

prompt_pwdのソースだと

 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) \$ '

みたいに適宜いじってください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む