---
# System prepended metadata

title: Mac driver note
tags: [Apple]

---

---
tags: Apple
---
# Mac driver note
slide: https://hackmd.io/@QSquirrel/HyUlguwGF


---
> 本篇將紀錄 macOS 中開發 System Extension 及 DriverKit 的相關資料 
> [name=Nick Xiao] [time=October 2021] [color=#907bf7]
>  
> Email: s9926004@gmail.com

{%hackmd ryr9Ug6sd %}

---

## 幫開發裝置掛上 Developer ID 金鑰

- Step1
    - 啟動台 > 鑰匙圈存取
- Step2
    - 鑰匙圈存取 > 憑證輔助程式 > 從憑證授權要求憑證
- Step3
    - 使用者電子郵件位址: username@gmail.com
    - 一般名稱: username
    - CA 電子郵件位址: 不用填
    - 已將要求: 儲存到磁碟
    - 點選”繼續”
- Step4
    - 儲存憑證至電腦
- Step5
    - [登入 developer 帳號](https://developer.apple.com/account/mac/certificate/distribution)
- Step6
    - 左邊選擇Certificates
    - 按下 “+”
- Step7
    - 選擇Developer ID Application and Kernel Extension
    - 按下 “Continue”
- Step8
    - 點選Choose File
    - 選取Step4所儲存的憑證
    - 按下 “Continue”
- Step9
    - 點選Download儲存憑證
- Step10
    - 開啟下載的憑證
- Step11
    - 點選”加入”
    - 確認是否加入成功


## 如何建立 Developer Profile 分支
由於 Developer ID Certificate 在到期前是有限且無法主動刪除的, 因此不同裝置在做開發時應該使用分支的方式, 允許擁有 Developer ID Certificate 以外的裝置開發.

:::warning
以下操作在已下載 Developer ID Certificate 的電腦上
:::

- Step1
    -  開啟Xcode > Preferences
- Step2
    - Accounts > Export Apple ID and Code Signing Assets
- Step3 
    - 輸入電腦密碼
- Stpe4
    - 設定developer profile的密碼

:::warning
以下操作為尚未下載Developer ID Certificate的裝置
:::

- Step1
    - 開啟Xcode > Preferences
- Step2
    -  Account > Import Apple ID and Code Signing Assets
- Step3
    - 載入剛剛所存的 developer profile
- Step4
    - 輸入剛剛所設定的developer profile密碼
- Step5
    - 按下OK


## 申請 Notarization 流程

- Step1 
    - 首先這邊有四個 shell script 在之後會用到
       <notarization.sh>
        ```Shell=
        #!/bin/sh
        
        FILE_PATH='/Users/nick/Desktop/Notarization/'
        KEXT_FILE_NAME='PeripheralDevice.kext'
        ZIP_FILE_NAME='PeripheralDevice.kext.zip'
        AC_USERNAME='username@gmail.com'
        AC_PASSWORD='aaaa-bbbb-cccc-dddd'
        BUNDLE_ID='com.username.driver.PeripheralDevice'

        #Apply a new app specific password:
        #https://appleid.apple.com/account/manage

        # create zip for app or kernel extension file
        ditto -c -k --keepParent $FILE_PATH$KEXT_FILE_NAME  $FILE_PATH$ZIP_FILE_NAME

        #Notarize app or kernel extension
        xcrun altool --notarize-app --primary-bundle-id "$BUNDLE_ID" --username "$AC_USERNAME" --password "$AC_PASSWORD" --file $FILE_PATH$ZIP_FILE_NAME

        #Check notarization history to get Request UUDI
        xcrun altool --notarization-history 0 -u "$AC_USERNAME" -p "$AC_PASSWORD"
        ```
        
        <notarization_check_approved.sh>
        ```Shell=
        #!/bin/sh

        FILE_PATH='/Users/nick/Desktop/Notarization/'
        KEXT_FILE_NAME='PeripheralDevice.kext'
        AC_USERNAME='username@gmail.com'
        AC_PASSWORD='aprl-awkg-pvmx-xunp'
        REQUEST_UUID='aaaa-bbbb-cccc-dddd'

        #Apply a new app specific password:
        #https://appleid.apple.com/account/manage

        #Get Notarization Info
        xcrun altool --notarization-info $REQUEST_UUID -u "$AC_USERNAME" -p "$AC_PASSWORD"
        
        ```
        
        <notarization_staple.sh>
        ```Sehll=
        #!/bin/sh

        FILE_PATH='/Users/nick/Desktop/Notarization/'
        KEXT_FILE_NAME='PeripheralDevice.kext'

        #Attach ticket to app or kernel extension
        xcrun stapler staple $FILE_PATH$KEXT_FILE_NAME

        #Validate notarization by xcrun stapler command again if necessary
        xcrun stapler validate $FILE_PATH$KEXT_FILE_NAME
        
        ```
        
        <notarization_check_notarization .sh>
        ```Shell=
        #!/bin/sh

        FILE_PATH='/Users/nick/Desktop/Notarization/'
        KEXT_FILE_NAME='PeripheralDevice.kext'

        #Verify the file has been notarized by spctl command
        spctl -a -t open --context context:primary-signature -v $FILE_PATH$KEXT_FILE_NAME
        
        ```
        
- Step2 
    - https://appleid.apple.com/account/manage/
    - 登入Apple ID
    - 產生密碼
- Step3
    - 編輯 ```notarization.sh```
    - 產生的密碼填至 ```AC_PASSWORD```
    - kernel extension 所在路徑填入至 ```FILE_PATH```
- Step4
    - 開啟 Terminal
    - 到 Shell Script 路徑
    - 執行 ```sh notarization.sh```
    - 取得RequestUUID
    
- Step5
    - 編輯 ```notarization_check_approved.sh```
    - Step4 取得的 RequestUUID 填至 ```REQUEST_UUID```
    - kernel extension 所在路徑填入至 ```FILE_PATH```
   
- Step6
    - 開啟 Terminal
    - 到 Shell Script路徑，執行sh 
    - ```notarization_check_approved.sh``` 確認有無錯誤
- Step7
    - 編輯 ```notarization_staple.sh```
    - kernel extension 所在路徑填入至 ```FILE_PATH```
    
- Step8
    - 開啟 Terminal
    - 到 Shell Script 路徑
    - 執行 ```sh notarization_staple.sh``` 確認有無錯誤
- Step9
    - 編輯 ```notarization_check_notarization.sh```
    - kernel extension 所在路徑填入至 ```FILE_PATH```
- Step10
    - 開啟 Terminal
    - 到 Shell Script路徑
    - 執行 ```sh notarization_check_notarization.sh``` 確認有無錯誤


## Xcode 設定注意事項
- 使用Xcode 7.0 以後的版本才能登入Apple ID 及選擇簽證, 新版的Xcode 如果沒有簽證會不能編譯
- Apple ID 登入: 上方工具列 -> Xcode -> Preferences -> Accounts

- Xcode上在General的設定部分有個" Automatically manage signing", 為了避免它一直找錯開發者帳號, 請取消掉, 自行設定簽章.
- 一台機器(電腦)要跑一次申請簽章的流程, 也可以同一組開發簽章, 開分支給其他台電腦
:::warning
分支簽章的有效期限和主要的有效期限有差, 請記得一開始是用哪一台的簽章做開發的. [(參考)](http://itouchs.blogspot.com/2015/04/mac-xcode.html
)
:::
-	Build Settings -> Architectures -> Base SDK 選擇 macOS
-	Build Settings -> User Defined : 這項目前不確定如何填寫, 全部留白
-	Info.plist (Information Property List)
:::info
目前實驗中, 基本上要根據開發環境的kernel 版本去設定OSBundleLibraries, 可以使用 uname –a 或者 sudo kextlibs PeripheralDevice.kext 查看.
:::

## Apple Silicon 平台注意事項
### XCode設定
- Build Settings:
    - Architectures >``` Standard architectures - $(ARCHS_STANDARD)``` 
    - User Define > VALID_ARCHS > ```x86_64 arm64e```

- Build: 
    Any Mac(產生Universal版Driver支援x86_64 + arm64e)
    ![](https://i.imgur.com/Eo2KWea.png)

- Info.plist: 
    LSRequiresNativeExecution: YES(If you never want users to run your app under Rosetta translation on Apple Silicon platform)
    ![](https://i.imgur.com/BMAEGmc.png)

### 在 Recovery Mode 的安全性規則允許 kernel extension
- Step1: Power off your Mac device
 
- Step2: Press and hold the power button until system go to the Recovery mode
- Step3: Click “Options” icon and press “Continue” button. If there is only one option “Security Policy”, please go to Step7 directly.
![](https://i.imgur.com/TH6eSPF.png =200x)
- Step4: Select user and press “Next”
- Step5: Menu > Utilities > Startup Security Utility
![](https://i.imgur.com/s2gyf5b.png =200x)
- Step6: Unlock
![](https://i.imgur.com/dfWyVV7.png =300x)
- Step 7: Click “Security Policy…” (安全性規則)
![](https://i.imgur.com/9lKmDwy.png =300x)
- Step 8: Select “Reduced Security”, and checked “Allow user management of kernel extensions from identified developers”
![](https://i.imgur.com/nuq5QIY.png =300x)


## 如何手動卸載/安裝 kernel extension
### 手動解除安裝kernel extension：
- Step1: 移除已存在kernel extension 
    MacOS 10.14 以前
    ```
    $ sudo rm -rf /System/Library/Extensions/PeripheralDevice.kext
    ``` 
    MacOS 10.15, 11.0 以後
    ```
    $ sudo rm -rf /Library/Extensions/PeripheralDevice.kext 
    ```
- Step2: 清除Staging Extensions
    MacOS 10.15 以前
    ```
    $ sudo kextcache --clear-staging
    ```
    MacOS 11.0以後
    ```
    $ sudo kmutil clear-staging
    ```
- Step3: 完整將kernel extension從啟動目錄移除(目前只有MacOS 11.0 Beta需要)
    1.	進入Recovery Mode
    2.	開啟Terminal並執行以下指令
    ```
    $ kmutil trigger-panic-medic --volume-root /Volumes/[Your Volume Name]
    ```
    3.	重新開機

### 手動安裝kernel extension：
- Step1: For Apple Silicon平台，請先按照”在Recovery Mode的安全性規則允許kernel extension”設定
- Step2: 將kernel extension複製到啟動目錄下
    MacOS 10.14以前
    ```
    $ sudo cp -R /System/Library/Extensions
    ```
    MacOS 10.15, MacOS 11以後
    ```
    $ sudo cp -R /Library/Extensions
    ```
- Step3: 修改 kernel extension 權限
    ```
    $ sudo chown -R root:wheel PeripheralDevice.kext
    $ sudo chmod -R 755 PeripheralDevice.kext
    ```
- Step4: 查看 kernel extension 是否有效
    :::info
    這裡會載入、檢查簽證、檢查版本以及檢查權限…等)
    :::
    MacOS 10.14 以前
    ```
    $ sudo kextutil -v /System/Library/Extensions/PeripheralDevice.kext
    ```
    MacOS 10.15 以後
    ```
    $ sudo kextutil -v /Library/Extensions/PeripheralDevice.kext
    ```
    MacOS 11 以後
    ```
    $ sudo kmutil –load –bundle-path /Library/Extensions/PeripheralDevice.kext
    ```
- Step5: System Preferences > Security & Policy > 點選Allow(首次安裝時會出現)
- Step6: 重新開機
- Step7: 透過檢視kernel extension狀態確認是否運作中
    MacOS 10.15 以前
    ```
    $ sudo kextstat | grep PeripheralDevice
    ```
    MacOS 11 以後
    ```
    $ sudo kmutil showloaded | grep PeripheralDevice 
    ```
- Step8: 透過檢視dmesg檢查IOLog的印字來確認是否運作中
    ```
    $ sudo dmesg | grep PeripheralDevice
    ```
### 手動卸載kernel extension：
MacOS 10.15 以前
```
$ sudo kextunload /Library/Extensions/PeripheralDevice.kext
```
MacOS 11 以後
```
$ sudo kmutil unload -p /Library/Extensions/PeripheralDevice.kext
```
### 手動載入kernel extension：
MacOS 10.15以前
```
$ sudo kextload /Library/Extensions/PeripheralDevice.kext
```
MacOS 11 以後
```
$ sudo kmutil load -p /Library/Extensions/PeripheralDevice.kext
```
## 測試尚未 Notarization 的 kernel extension
- Step1. 
    - 進入Recovery Mode:
	- Apple Silicon平台: 關機後，按住開機鍵直到燈號轉橘色，點Options進入一般平台: Command + R 

- Step2. 
	- Utilities > Terminal
	- csrutil status確認狀態
	- csrutil disable 關閉SIP
	- reboot

- Step3. 
	- 按照手動安裝 kernel extension 步驟安裝即可
- Step4. 
	- 測試完畢後按照手動卸載 kernel extension 步驟卸載
- Step5. 
	- 重新進入Recovery Mode，開啟Terminal
	- csrutil enable
	- reboot

## 參考資料
允許kernel加載
https://developer.apple.com/library/archive/technotes/tn2459/_index.html

Apple後台登入管理(憑證等等):
https://developer.apple.com/account/mac/certificate/distribution

Apple建立分支教學:
http://itouchs.blogspot.com/2015/04/mac-xcode.html

Xcode 說明:
https://help.apple.com/xcode/mac/8.0/#/devdc0193470

macOS SDK
https://github.com/phracker/MacOSX-SDKs/releases

建立kernel文件
https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/build/build.html

Xcode 設定(apple)
https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptIOKit/iokit_tutorial.html#//apple_ref/doc/uid/20002366

Notarization
https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution
https://developer.apple.com/documentation/xcode/notarizing_your_app_before_distribution/customizing_the_notarization_workflow
https://forums.developer.apple.com/message/389982#389982

建立Developer Profile分支
https://help.apple.com/xcode/mac/current/#/dev8a2822e0b
https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E8%BC%B8%E5%87%BA%E4%B8%8A%E6%9E%B6-ios-app-%E4%B8%8D%E8%83%BD%E6%B2%92%E6%9C%89%E7%9A%84-private-key-5d935ede10c8

Apple Silicon相關
https://developer.apple.com/documentation/xcode/porting_your_macos_apps_to_apple_silicon
https://developer.apple.com/documentation/xcode/building_a_universal_macos_binary

Apple Silicon的DTK的OS下載網頁
https://developer.apple.com/download/universal/

Recovery mode redo coming to Apple Silicon Macs
https://www.imore.com/recovery-mode-redo-coming-apple-silicon-macs

Explore the new system architecture of Apple silicon Macs
https://developer.apple.com/videos/play/wwdc2020/10686/

各種範例:
https://bbs.pediy.com/thread-197990.htm
https://www.itread01.com/content/1535307613.html
http://www.tanhao.me/pieces/1547.html/
http://www.tanhao.me/pieces/1545.html/
http://www.tanhao.me/pieces/1525.html/
http://www.tanhao.me/pieces/1515.html/
https://www.jianshu.com/p/232022a08ba4
