MacBookのNVRAM設定（特にオートブート）

これはMacBookに関するメモです
私はPro2016のMojave最新版＋サブモニターを使っています
（故に常にサブモニター付きで挙動を確認しています）
他年代のPro（特に2018以降）やAir系や無印系はよくわからないです
一切の操作をする時は自己責任でお願いします
なおこの記事を書き始めた時点で設定は既にカスタム済みです

# NVRAM
Macの中に入っている基本的な設定やシステムの中心に関する情報を保存しているメモリのこと
（ところで似たようなものらしいPRAMってなんだろう）
[リセット](https://support.apple.com/ja-jp/HT204063)すると出荷時の設定に戻すことができる（サポートページ）
ハードウェア的な設定はSMCに入っているらしい，こちらも[リセット](https://support.apple.com/ja-jp/HT201295)すると出荷時の設定に戻すことができる（サポートページ）

# AutoBoot
電源ボタンを押さなくても特定操作をすると勝手に起動する仕様
MacBookPro2016から実装され，2018からは対象となる条件が増やされた（T2チップ採用からか）
NVRAMに設定が存在しており，terminalから編集して値を変更することができる
デフォルトの設定値は**%03**になっているが，結論から言うと私は**%01**にした

# nvram
terminalから設定できるユーティリティ

## man
とりあえず覗いてみる

```bash
man nvram
```

ちなみに一番下までスクロールして読み終わったら```:q```を打って抜けられる


<details><div>

```
nvram(8)                                                                                                                                                            nvram(8)

NAME
       nvram - manipulate firmware NVRAM variables

SYNOPSIS
       nvram [ -p ] [ -f filename ] [ -d name ] [ -c ] [ name [= value ]] ...

DESCRIPTION
       The  nvram  command  allows manipulation of firmware NVRAM variables.  It can be used to get or set a variable.  It can also be used to print all of the variables or
       set a list of variables from a file.  Changes to NVRAM variables are only saved by clean restart or shutdown.

       In principle, name can be any string.  In practice, not all strings will be accepted.  New World machines can  create  new  variables  as  desired.   Some  variables
       require administrator privilege to get or set.

       The  given value must match the data type required for name.  Binary data can be set using the %xx notation, where xx is the hex value of the byte.  The type for new
       variables is always binary data.

OPTIONS
       -d name
              Deletes the named firmware variable.

       -f filename
              Set firmware variables from a text file.  The file must be a list of "name value" statements.  The first space on each line  is  taken  to  be  the  separator
              between "name" and "value".  If the last character of a line is \, the value extends to the next line.

       -x     Use XML format for reading and writing variables.  This option must be used before the -p or -f options, since arguments are processed in order.

       -c     Delete all of the firmware variables.

       -p     Print all of the firmware variables.

EXAMPLES
              example% nvram boot-args="-s rd=*hd:10"

       Set the boot-args variable to "-s rd=*hd:10".  This would specify single user mode with the root device in hard drive partition 10.

              example% nvram my-variable="String One%00String Two%00%00"

       Create a new variable, my-variable, containing a list of two C-strings that is terminated by a NUL.

              example% nvram -d my-variable

       Deletes the variable named my-variable.

                                                                              October 28, 2003                                                                      nvram(8)

```

</div></details>


## ファイル

NVRAMに保存されているものなのでmacOS上に存在しない
気になる人は中身を出力してファイルにしてみるべし

## 現状確認

+ 全ての情報を見る

```bash
nvram -p
```

+ これだと見にくいのでXML形式で見る

```bash
nvram -xp
```

+ AutoBootだけ見たい

```bash
nvram -p | grep AutoBoot
```

当てはまる数値は通常だと

```bash
AutoBoot    %01
```

XML形式だと

```xml
    <key>AutoBoot</key>
    <data>
    AQ==
    </data>
```

というように表示される


### バイナリ覗き

おまけ

<details><div>

```bash
touch nvramsettings.xml
nvram -p > nvramsettings.xml
```

この状態で該当するデータは``` 253031 ```，表示は``` %01 ```

```bash
touch nvramsettings2.xml
nvram -xp > nvramsettings.xml
```
この状態で該当するデータは``` 41513D3D ```，表示は``` AQ== ```

末尾が＝といえばBASE64なので```A```は```000000(2)```で```Q```は```010000(2)```，2つを繋げて```000000010000(2)```さらに1バイトすなわち4ビット区切りの16進数で換算すると3バイト分の```0x010```
これは「```0x01```つまり『```1```』をBASE64に変換する過程でビット数を6の倍数にする必要があったために0を4つ足した（たまたま1バイト分になっちゃった）」という仮説が整合性高いと思う（小並感）
というよりもmanにその答えが書いてあり，今回の設定は全てバイナリ単位で書き換えていることがわかった

```bash
The given value must match the data type required for name.  Binary data can be set using the %xx notation, where xx is the hex value of the byte.  The type for new variables is always binary data.
```
> 与えられる値は対応する名前が要求するものに必ず合わせてください．バイナリデータは```%xx```の記法で与えることができ，```xx```は16進数の書き方を用いてください．新しい変数の型は常にバイナリデータです．

これ実はハードウェアレベルのセッティングをしているんだなぁって・・・

</div></details>

## 書き換え方法

2種類あるが今回は後者を選ぶ
sudo権限が必要

+ txtファイルを用意して読み込ませる

これは必ずUTF-8で書式を合わせること（文を読む限りだとこんな感じっぽい）

```txt:nvramset.txt
<name1>,<value1>
<name2>,<value2>
```
```bash
sudo nvram -f nvramset.txt
```

+ terminalから1つずつ書き換える

```bash
sudo nvram <name>=<value>
```

### 実践
これはあくまで一例

```bash
sudo nvram AutoBoot=%01
```

# 各設定値の挙動

みんなもやってみよう
なお電源ボタンを押せば必ず起動する
また「外部ディスプレイがない」かつ「蓋が閉じている」かつ「充電を開始する」際はいずれも起動しない
そして%00~%02においては「蓋が閉じている」かつ「充電を開始する」際はいずれも起動しない

## AutoBoot=%00
何をしても常に沈黙，**充電ケーブルを挿しても全く充電されない**程の徹底ぶりを見せる
ネットによく転がっている解説サイトが載せているパターン

## AutoBoot=%01
充電されていない状況では沈黙，「充電されながら蓋を開く」際にのみ起動する
%00と異なり蓋が閉じていようが「常に充電を受け付ける」が，かと言って「充電時に蓋を開いても反応しない」という**良いとこ取り**はできなかった
「蓋が開いたまま充電が始まる」際は起動しない

## AutoBoot=%02
「蓋を開く」際に必ず起動するが，「蓋が開いたまま充電が始まる」際は起動しない

## AutoBoot=%03
デフォルトの設定値
「蓋を開く」もしくは「充電が始まる」で起動する

## AutoBoot=%04
コレ以降は流石に怖くてやっていない，%04以上の設定値が存在する可能性は限りなく低そうなので・・・
人柱の情報あれば求む


# 他にもNVRAM設定でやれそうなこと
以下推測と調べ物

## LocationServicesEnabled
デフォルトは```AQ==```つまり```0x01```
位置情報の利用の許可

## SystemAudioVolume

``` Nw== ```つまり```0x37```
起動音等の音量設定，でも起動音とかを聞いたことがない

## SystemAudioVolumeDB

``` 5A== ```つまり```0xE4```
（SystemAudioVolumeと何が違うのかわからない，ググってもわからず）

## backlight-level

``` fgE= ```つまり```0x7E 0x01```
ディスプレイ輝度の調整

## good-samaritan-message

``` RW50ZXIgaGVyZQ== ```つまり```Enter here```
これはなんとGUIから各個人が設定できる
<img width="668" alt="スクリーンショット 2020-01-22 22.37.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540440/c8380e4a-1d09-1703-3c8b-025130bd0424.png">
日本語訳で「**善きサマリア人のメッセージ**」，これはログイン画面で表示するメッセージ
[参考](https://apple.stackexchange.com/questions/229674/10-11-good-samaritan-message-not-showing-on-filevault2-unlock-screen)

### 脇道

<details><div>

ログイン画面の壁紙の変更はSIPに阻まれているのは有名・・・そういえばkextもSIPに阻まれていたような・・・
ところで「善きサマリア人」といえばルカ福音書10章33節ですが，その中の例え話（「善きサマリア人の例え」と呼ばれる）に
> 民族の垣根を超え慈悲で人助け（実質的には医療措置）をするサマリア人

がいまして，それが転じて一般的に「good Samaritan」＝「善良で慈悲深い人間」というフレーズが生まれました
さらにそこから派生した「サマリア人の法」はそういった人間を保護するための概念であり，
> 災難に遭ったり急病になったりした人など（窮地の人）を救うために無償で善意の行動をとった場合、良識的かつ誠実にその人ができることをしたのなら、たとえ失敗してもその結果につき責任を問われない

に基づき医療関係者の責任免除を明確に定める法が存在する国があります
一方では日本では分野によって独自に緊急事態の行為に免責が認められる法が点在しており，しかしそれは訴訟で争われることが多い事項でもあります

</div></details>

## gpu-policy
デフォルトは```AQ==```つまり```0x01```
GPUというよりグラボの利用設定
1だと起動する，つまり0だと起動すらしなくなるらしい・・・自機にグラボが入っているので本当に危ない・・・
（[参考](https://github.com/ah-/switcher/issues/2)）

## prev-lang:kbd
デフォルトは```amE6MjUy```つまり```ja:252```
キーボードの言語設定
非ラテン系キーボードに必要らしい，でも私が使っているのはUSキーボードなのに・・・
おそらくリカバリーモード等で用いられる言語設定に関係していると思う
（海外のHackintoshガチ勢の方による[参考](https://github.com/khronokernel/Getting-Started-With-OpenCore/blob/master/README.md)）

# まとめ

AC電源未接続のまま不慮の事態でパカっと開いて電気をロスしないかつ充電はやってくれる%01がおすすめ
BASE64の換算を初めてやった