snap入门

笔记

重要notes:

  • MLO,uboot.img 和原来一样bare type放到mmc的指定位置。
  • system-boot区中是kernel-snap
  • initrd在kernel-snap中
  • 通过ubuntu-image生成 bootable image, (包括gadget snap, kernel snap, core snap 以及其他app snap), 通过dd烧写image到sd card(或emmc)

1 简介.

ubuntu core 由4 类snap 构成,gadget snap, kernel snap , core snap , app snaps。

  • gadget snap 是包含了uboot image,系统镜像的布局,IO 接口的权限,系统的默认属性设定(usb 自动挂载属性等),gadget snap 描述了这个设备几乎所有的属性。
  • kernel snap 包含kernel & ubuntu core 所需要的initrd 的snap。
  • core snap 包含ubuntu core rootfs 的snap 包
  • app snap 关于包含app 的snap。

传统的系统启动需要uboot,kernel,rootfs, app, ubuntu core 也一样,只不过他们都是以snap 包的形式存在于ubuntu core 中的。那么问题来了? snap 包是一个只读的squashfs 文件系统的文件,ROM code /SPL 如何读取它并启动对应的启动镜像呢 ? 要知道SPL,甚至uboot 当前都不支持squashfs 的文件系统哦.

事实上,当用ubuntu-image 命令制作系统启动镜像的时候,该命令会将gadget snap & kernel snap 中的启动image 全部解压出来,(同时解压一部分core 的内容) 放到gadget.yaml 中指定的分区中去。这样当制作好镜像后,uboot,kernel , 和initrd 的存在形式就和传统的系统一样了, 即以启动文件的形式存在。当系统启动到initrd 阶段, 由initrd 在writable 中准备一套可启动的文件,并启动它。之后,snapd 启动,开启snap 的世界。

不过在系统镜像里,仍然保存了gadget snap 和kernel snap, 这是为了以后这些snap 能够进行顺利的更新,回滚做准备的。

在ubuntu core 中, 每一个snap 被安装后, 该snap 就通过/dev/loopx 挂载到/snap/${snap_name}/ 下的版本文件夹下, 是一个只读的文件系统

1.1 Core 的user

制作好的Ubuntu core启动镜像是不存在用户的,在系统第一次启动时,用户可以根据需要创建两种账户:

  1. SSH user , 只能用于远端SSH 登录,不能用于本地console 登录;
  2. system user, 既可以用于本地登录, 也可以用于远程ssh 登录;

创建SSH 账户的方法是链接网线, 然后根据需求配置网络,最后生成ssh 登录的账户;

创建system user 参照 :

https://docs.ubuntu.com/core/en/guides/manage-devices/?_ga=2.226522645.905063160.1536053910-560405323.1510796397

一旦创建了 ubuntu core 的账户,该用户就管理了该设备, 系统将不再允许去创建其他账户去管理这个设备。 root 权限可通过 sudo su 来切换。

1.2 Core 的安全机制之interfaces

ubuntu core 中为了 安全, 几乎访问仍何重要资源都需要申请,如何申请?

ubuntu core 提供了interface 机制, interfaces 的名字代表了这种资源, 一般地,这种资源需要slots 来提供资源访问权限, plug 来获取使用资源的权限。

  • core 中已经提供了大部分通用的,和硬件无关的slots,
  • 还有一部分硬件相关的interfaces slot 由 gadget 提供,
  • 另外一部分interfaces slot由 snap app 提供。

一个需要申请interface 的APP 在安装后, 如果他的plug 和core/gadget/other snap 提供的slot 没有链接, 直接执行这个snap 程序,会被APParmor(后续会讲)所阻止,返回没有权限的错误, 即使root 也会如此。 链接interfaces 的命令如下:

#  查看系统提供的interfaces 链接状况
$ snap interfaces
# 链接plug & slot
$ snap connect snap_package:interface     core/gadget/other snap:slot
$ snap disconnect snap_package:interface     core/gadget/other snap:slot

一旦链接成功,将会永久保存。disconnect 也是如此。

有些interfaces 在安装时是自动链接,有些需要手动链接。 详细请参考如下链接:https://docs.snapcraft.io/reference/interfaces

有一些snap 需要访问一个硬件接口,当前ubuntu core 还没有定义,这时候在安装时需要加入一些参数来跳过apparmor 的限制。
snap install --dangerous xx.snap

有些时候,你需要对snap 进行debug, ubuntu 官方提供了snappy-debug 又来debug 你的snap app, 例如你需要debug 一个snap 在security 方面的内容时,可按照如下方式进行:

$snappy-debug.security scanlog &
# then, run your snap , and there are some debug message for this snap

2 制作ARM 版本的ubuntu core

制作ARM 版本的ubuntu core, 有三个snap 包需要准备:gadget snap, kernel snap , core snap,由于core snap 由ubuntu 官方提供,故需要制作gadget & kernel 的snap 包, 下来我们将会一一描述

2.1 gadget snap 制作

gadget snap 中包含了uboot 镜像,以及生成的sdcard 镜像的分区定义,以及分区的放置内容, 设备接口的访问权限… 等功能。

2.1.1 Ubuntu core 对uboot 的更改

  1. 环境变量处在启动设备的第一个fat 分区

这是snapd 的要求,snapd 在系统启动后,会读取第一个fat 分区的环境变量文件,并根据相关设定,做出对应的行为,同时还会修改相关环境变量的值。为了支持uboot 环境变量处在EMMC 中, 你需要做如下修改:

/* env is in fat */
#define CONFIG_ENV_IS_IN_FAT   
#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
#define FAT_ENV_INTERFACE              "mmc"
#define FAT_ENV_DEVICE_AND_PART                "0:1"
#define FAT_ENV_FILE                   "uboot.env"
#define CONFIG_ENV_SIZE      (128 * 1024)
#define CONFIG_FAT_WRITE
#define CONFIG_SUPPORT_RAW_INITRD

CONFIG_SYS_REDUNDAND_ENVIRONMENT 必须添加, 原因为何?

  • 假设一个情景,当snapd 设定某些环境变量后正在保存时(一般的文件保存需要花费一些时间),突然断电, 下次启动时这个状态并没有改正过来。为了防止这一点, 你需要加入CONFIG_SYS_REDUNDAND_ENVIRONMENT,让环境变量保存时,写入一个特殊的头部标记,这告诉snapd 在操作该文件是都是原子的,从而减小这种风险。
  • CONFIG_ENV_SIZE 必须为128 K, 这也是固定的;
  • CONFIG_FAT_WRITE 确保能进行环境变量的保存;
  • CONFIG_SUPPORT_RAW_INITRD: 为了支持uboot 能够导入initrd ,因为 ubuntu core 的启动,必须要使用initrd.

至此, 就完成了让环境变量处在启动设备的第一分区的任务。

  1. 添加snapd 等需要的环境变量
    我们刚才说过snapd 需要uboot 环境变量, 接下来,我们就看需要什么变量?
+       "snap_mode=\0" \
+       "initrd_addr=0x88080000\0" \
+       "initrd_file=initrd.img\0" \
+       "kernel_file=kernel.img\0" \
+       "snap_try_kernel=rsb4220-kernel_x1.snap\0" \
+       "snap_try_core=core_5331.snap\0" \
uEnv.txt
loadfdt=load mmc ${bootpart} ${fdtaddr} ${snap_kernel}/dtbs/${fdtfile}
loadkernel=load mmc ${bootpart} ${loadaddr} ${snap_kernel}/${kernel_file}
loadinitrd=load mmc ${bootpart} ${initrd_addr} ${snap_kernel}/${initrd_file}; setenv initrd_size ${filesize}
loadfiles=run loadkernel; run loadinitrd; run loadfdt
snappy_cmdline=rng_core.default_quality=700 net.ifnames=0 init=/lib/systemd/systemd ro panic=-1 fixrtc
snappy_boot=if test "${snap_mode}" = "try"; then setenv snap_mode "trying"; saveenv; if test "${snap_try_core}" != ""; then setenv snap_core "${snap_try_core}"; fi; if test "${snap_try_kernel}" != ""; then setenv snap_kernel "${snap_try_kernel}"; fi; elif test "${snap_mode}" = "trying"; then setenv snap_mode ""; saveenv; fi; mmc dev ${mmcdev}; if mmc rescan; then echo SD/MMC found on device ${mmcdev}; if run loadfiles; then setenv mmcroot "/dev/disk/by-label/writable ${snappy_cmdline} snap_core=${snap_core} snap_kernel=${snap_kernel}"; setenv args_mmc "run finduuid;setenv bootargs console=${console} ${optargs} root=${mmcroot}"; run args_mmc; bootz ${loadaddr} ${initrd_addr}:${initrd_size} ${fdtaddr}; fi; fi
uenvcmd=run snappy_boot

为了启动ubuntu core, 我们需要添加新的启动方式,其行为定义在snappy_boot 中,snap_mode,

snap_kernel , snap_core 这些都是snapd 需要的,用来启动正确的kernel & core snap.

snappy_cmdline 是给kernel的传参,有些参数会被initrd 进行分析,来解压/挂载 对应snap 包。

panic=-1 告诉kernel,如果出现panic,就自动重启,而不是卡在那里。

mmcroot “/dev/disk/by-label/writable …” 表明系统最终的rootfs 在writable ,刚制作好的SD卡的writable 中并没有可运行rootfs,这个工作是由initrd 来负责完成的。所以initrd 必不可少。

至此, 便完成了uboot 源码部分的更改。

2.1.2 创建gadget.yaml

和其他的snap 包不同, gadget snap 需要一个gadget.yaml 来描述设备镜像的分区, 分区中的内容,设备树的放置位置,设备接口的访问权限等问题。总之,gadget.yaml 定义了关于这个device 的一切特殊信息。
接下来我们描述下gadget.yaml 的语法:

# Define the format of this file. The default and latest format is zero.
# Clients reading this file must reject it the format is greater than
# the supported one. (optional)
format: <int>
# Default configuration options for defined snaps, applied on installation.
# The snap ID may be discovered via the snap info command.
# Since 2.33 snap ID can be the "system" nick to cover the system
# configuration. (optional)
defaults:
    <snap id>:
        <key>: <value>
# Interface connection instructions for plugs and slots of seeded
# snaps to connect at first boot. snap IDs can be the "system"
# nick as well. Omitting "slot" in an instruction is allowed
# and equivalent then to: slot: system:<plug>
# (since 2.34) (optional)
connections:
   -  plug: <plug snap id>:<plug>
      slot: <slot snap id>:<slot>
     
# If device-tree is specified, `dtbs/<filename>` must exist in kernel or
# gadget snap (depends on origin) and `snap_device_tree_origin` and
# and `snap_device_tree` are made available for u-boot and grub. (optional)
device-tree: <filename>
# Defines where the device tree is. Defaults to gadget. (optional)
device-tree-origin: kernel
# Volumes defining the structure and content for the images to be written
# into one ore more block devices of the gadget device. Each volume in
# in the structure represents a different image for a "disk" in the device.
# (optional)
volumes:
  # Name of volume and output image file. Must match [a-z-]+. (required)
  <volume name>:
    # 2-digit hex code for MBR disk ID or GUID for GPT disk id. (optional)
    id: <id>
                  
    # Bootloader in the volume. Required in one volume. (required/optional)
    bootloader: grub | u-boot
    # Which partitioning schema to use. Defaults to gpt. (optional)
    schema: mbr | gpt | mbr,gpt
    # Structure defines layout of the volume, including partitions,
    # Master Boot Records, or any other relevant content. (required)
    structure:
      - # Structure value is a list.
        # Structure item name. There's an implementation-specific constraint
        # on the maximum length. The maximum length of a partition name
        # for GPT is 36 characters in the UTF-16 character set. (optional)
        name: <name>
        # GPT unique partition id, disallowed on MBR volumes. (optional)
        id: <id>
        # Role defines a special role for this item in the image. (optional)
        # Must be either unset, or one of:
        #   mbr - Master Boot Record of the image.
        #   system-boot - Partition holding the boot assets.
        #   system-data - Partition holding the main operating system data.
        #
        # A structure with role:system-data must either have an implicit
        # file system label, or 'writable'.
        role: mbr | system-boot | system-data
        # Type of structure. May be specified as a two-hex-digit MBR partition
        # type, a GPT partition type GUID, or both on hybrid schemas.  The
        # special value `bare` says to not create a disk partition for this
        # structure. (required)
        type: <mbr type> | <gpt guid> | <mbr type>,<gpt guid> | bare
        # Size for structure item. Maximum of 446 for the mbr role. (required)
        size: <bytes> | <bytes/2^20>M | <bytes/2^30>G
        # The offset from the beginning of the image. Defaults to right after
        # prior structure item. (optional)
        offset: <bytes> | <bytes/2^20>M | <bytes/2^30>G
        # Offset of this structure element (in units of 512-byte sectors) is
        # written to the provided position within the volume in LBA48 pointer
        # format (32-bit little-endian). This position may be specified as a
        # byte-offset relative to the start of another named structure item.
        # (optional)
        offset-write: [<name>+]<bytes> |
                      [<name>+]<bytes/2^20>M |
                      [<name>+]<bytes/2^30>G
        # Filesystem type. Defaults to none. (optional)
        filesystem: none | vfat | ext4
        # Filesystem label. Defaults to name of structure item. (optional)
        filesystem-label: <label>
        # Content to be copied from gadget snap into the structure. This
        # field takes a list of one of the following formats. (required)
        content:
            # Copy source (relative to gadget base directory) into filesystem
            # at target (relative to root). Directories must end in a slash.
            - source: <filename> | <dir>/  # (required)
              target: <filename> | <dir>/  # (required)
            # Dump image (relative to gadget base directory) of the raw data
            # as-is into the structure at offset. If offset is omitted it
            # defaults to right after prior content item. If size is omitted,
            # defaults to size of contained data.
            - image: <filename>                                 # (required)
              offset: <bytes> | <bytes/2^20>M | <bytes/2^30>G   # (optional)
              offset-write: (see respective item above)         # (optional)
              size: <bytes> | <bytes/2^20>M | <bytes/2^30>G     # (optional)

我们给出一个example:

device-tree: am335x-boneblack
device-tree-origin: kernel
volumes:
  disk:
    bootloader: u-boot
    schema: mbr
    structure:
      - name: mlo
        type: bare
        size: 131072
        offset: 131072
        content:
          - image: MLO
      - name: u-boot
        type: bare
        size: 786432
        offset: 393216
        content:
          - image: u-boot.img
      - name: system-boot
        type: 0C
        filesystem: vfat
        filesystem-label: system-boot
        size: 128M

这个gadget 只定义了一个分区,那就是system-boot 分区, 它主要默认存放kernel sanp, uboot.env 等文件。
MLO,uboot.img 类似于被dd 到对应的MMC 的位置上了。这是对上面文件的翻译,细节可以参考上面gadget 的语法部分。

2.1.3 创建snap.yaml

我们直接给出一个example:

name: rsb4220
version: 16-0.4
summary: am335x advantech board
description: |
Bootloader files and partitoning data to create a
bootable Ubuntu Core image for am335x advantech board.
type: gadget
architectures:
  - armhf
confinement: strict
grade: stable
parts:
  uboot:
    plugin: nil
    source: .
    build: |
      echo "building ..."
    install: |
      cp u-boot.img $SNAPCRAFT_PART_INSTALL/
      cp uboot.env  $SNAPCRAFT_PART_INSTALL/
      cp uEnv.txt   $SNAPCRAFT_PART_INSTALL/
      cd $SNAPCRAFT_PART_INSTALL/; ln -s uboot.env uboot.conf
slots:
  gpio200:
     interface: gpio
     number: 200
  gpio201:
     interface: gpio
     number: 201
  gpio202:
     interface: gpio
     number: 202
  gpio203:
     interface: gpio
     number: 203
  gpio204:
     interface: gpio
     number: 204
  gpio205:
     interface: gpio
     number: 205
  gpio206:
     interface: gpio
     number: 206
  gpio207:
     interface: gpio
     number: 207
  serial0:
     interface: serial-port
     path: /dev/ttyO0
  serial1:
     interface: serial-port
     path: /dev/ttyO1
  serial2:
     interface: serial-port
     path: /dev/ttyO2
  serial3:
     interface: serial-port
     path: /dev/ttyO3
  serial4:
     interface: serial-port
     path: /dev/ttyO4
  serial5:
     interface: serial-port
     path: /dev/ttyO5
  i2c-0:
     interface: i2c
     path: /dev/i2c-0

2.2 kernel snap 的制作

kernel snap 和gadget 一样,是一个特殊的snap, ubuntu-image 在制作镜像时,会将kernel snap 解包出来,放在system-boot 分区。 ubuntu core 需要kernel 做出一些更改, 例如是能apparmor,snappy,squanfs 的支持等。

2.2.1 ubuntu core 对kernel 的更改

ubuntu core 对kernel 的需求还是挺多的, 具体可以参考https://github.com/snapcore/sample-kernels。
这个kernel 有不同的版本,你可以根据你的版本,选择最接近的kernel 版本。
这个改动基本分为两个部分:
1) kernel config 的配置
根据kernel/configs/snappy/ 下的config 添加自己的config
2) Apparmor 的修正:
根据该sample-kernel 的修改历史, 修改apparmor, 由于patch 较多,更改时需要多加注意,一旦改动不当,就会导致snapd 无法正常运行。
至此, kernel 源码部分就已经修改完成。

2.2.2 获取并定制initrd

ubuntu core 的core snap 中携带了initrd, 而正真携带initrd 的snap 是kernel snap。 所以在制作kernel snap 前, 需要下载core snap,使用以下命令获取initrd:

$  UBUNTU_STORE_ARCH=armhf  snap download   core
core_5331.snap
$ unsquashfs  core_5331.snap   ## 解压core snap
$  cp squashfs-root/boot/initrd.img-core-0.7.43+ppa25     initrd.img

当获取initrd.img 后,就可以根据需求定制你的initrd, 当然你也可以选择不做仍何定制。接下来我们介绍如何解压initrd/压缩initrd的命令。

  1. 解压ubuntu core 提供的 initrd

参照snapcraft 提供的kernel 插件, 可以用以下命令解压:
$ xz -dc initrd.img | cpio -id

2) 压缩生成initrd
$ find . | cpio --create --format=newc | lzma > ../initrd.img
至此,initrd 制作完成, copy kernel image , dtb, 和 initrd 到同一目录。

2.2.3 创建snapcraft.yaml

由于我们的kernel image 是预编译好的, 所以,我们只提供一个简单kernel snap 的yaml。

name: rsb4220-kernel
version: 4.4.19-gff01773757
summary: advantech kernel
description: advantech kernel sanp for rsb4220
type: kernel
architectures: [ armhf ]
confinement: strict
grade: stable
parts:
  kernel:
    plugin: nil
    source: .
    build: |
      mkdir -p $SNAPCRAFT_PART_INSTALL/dtbs
    install: |
      cp zImage $SNAPCRAFT_PART_INSTALL/kernel.img
      cp am335x-rsb4220a1.dtb  $SNAPCRAFT_PART_INSTALL/dtbs
      cp initrd.img  $SNAPCRAFT_PART_INSTALL/
      tar xvzf modules.tar.gz  -C $SNAPCRAFT_PART_INSTALL/

Kernel snap 的type 必须是kernel,其他均是kernel 构建kernel snap 的基本操作。
执行snapcraft --target-arch=armhf 来生成kernel snap。

2.3 ubuntu core 系统镜像

根据前面的讲解,基本可以制作出你自己的gadget snap & kernel snap. 如何将这些snap 生成最终的sdcard/emmc image将是本章的主要内容,同时还会描述如何创建loacal user。

2.3.1 生成ubuntu core image

ubuntu core 提供了一个生成ubuntu core image 的工具,你可以下面的方式进行下载
snap install ubuntu-image
下载完成后,你需要实现一个断言(assert)来定义你生成image 中所包含的snap 包,请按照如下链接进行注册

https://ubuntu.com/core/docs/image-building

根据这个链接,你将会顺利生成sdcard/emmc 的image。

Inside a model assertion
Creating an Ubuntu Core image starts with a model assertion, a digitally signed text file with structured headers defining every aspect of the image.

{
    "type": "model",
    "series": "16",
    "authority-id": "canonical",
    "brand-id": "canonical",
    "model": "ubuntu-core-20-amd64",
    "architecture": "amd64",
    "timestamp": "2019-11-14T07:13:24.0Z",
    "base": "core20",
    "grade": "signed",
    "snaps": [
        {
            "name": "pc",
            "type": "gadget",
            "default-channel": "20/stable",
            "id": "UqFziVZDHLSyO3TqSWgNBoAdHbLI4dAH"
        },
        {
            "name": "pc-kernel",
            "type": "kernel",
            "default-channel": "20/stable",
            "id": "pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza"
        },
        {
            "name": "core20",
            "type": "base",
            "default-channel": "latest/stable",
            "id": "DLqre5XGLbDqg9jPtiAhRRjDuPVa5X1q"
        },
        {
            "name": "snapd",
            "type": "snapd",
            "default-channel": "latest/stable",
            "id": "PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4"
        }
    ]
}

https://ubuntu.com/core/docs/board-enablement#heading–image-building

  • Sign the model assertion
  • Image building
$ sudo ubuntu-image \
-c stable \        # available channels are: edge/beta/candidate/stable
--image-size 4G \
--extra-snaps <gadget snap file name, e.g. roseapple-pi_16.04-1_armhf.snap> \
--extra-snaps <kernel snap file name, e.g. roseapple-pi-kernel_3.10.37-1_armhf.snap> \
--extra-snaps <add more preinstalled snaps here, names from the store or local paths> \
-o <image output file name, e.g. roseapple-pi-20161107-0.img> \
<model file name, e.g. roseapple.model>

Your image is ready, you can use a tool like dd to write the image to an SD Card and boot your board.

  • Build a custom image for a reference board

2.3.2 创建ubuntu core 的user

当插入SD卡,系统第一次正常启动后,你会发现系统并没有登录界面,而是需要你配置自己的网络,之后根据提示输入你在ubuntu core 注册时用的邮箱& passwd。 完成之后,同样没有登录界面, 这是为何?
原来,ubuntu core 这种默认的user 被按照上面的方式创建后,只能通过SSH 登录。而且一旦存在一个user, 将不能创建其他user 来管理这个设备。
在创建这种默认的 user 时,如果有两个网口,core将会要求每个网口都要能链接上internet,否则就会配置失败,或许这是一个bug,在后面的版本中应当被ubuntu core 所修正。
ubuntu core 也支持另外一种user 即system user 的创建。 system user 像普通的ubuntu 一样,可以直接在本地登录,同时也支持ssh 等的登录。 一旦被创建,将不能再创建其他user 来管理这个设备。 system user 的创建需要导入一个auto.import.assert的断言,用以描述创建用户的信息。
具体创建方法可以参考如下链接:https://docs.ubuntu.com/core/en/guides/manage-devices/?_ga=2.226522645.905063160.1536053910-560405323.1510796397
文章中说只要把文件放入udisk 就会自动产生system user, 但经过笔者在am335x 上测试,是不行的,事实上,这个assert 可以放在仍何被系统挂载的分区的根目录。(如果调试不okay, 可以将其放在writable分区中)
在创建system user 的断言时, 所使用的model 断言必须是之前创建sdcard image 时所用的断言, 签名所用的key 可以不一致, 但必须由之前的model 来定义。
至此,就完成创建 ubuntu core 系统的所有工作, 登录系统后,一切操作就像原来的ubuntu 一样简单,只不过apt-get install 换成了snap install, 一切都进入了snap 的世界。

3. app 开发相关

进入snap 世界后, shell 还能用么?

必须能用,而且还和之前一样好,同时还支持snap 的运行。 snap 的世界是由snapd 构建起来的,而snapd 只是ubuntu core 中的一个守护进程。 看到这里你就会明白,snap 是在shell 之上的概念。 你可以完全使用shell 命令和之前一样,这也不存在ubuntu core 里面讲的权限, interface 之类的概念, 这些概念只存在snap 的世界里, 和shell 无关。

不过ubuntu core 推荐我们使用snap , 因为ubuntu core 就是为snap 而生的。

3.1 创建一个snap app

细节请参照下面的demo:

https://tutorials.ubuntu.com/tutorial/build-a-nodejs-service?backURL=https://docs.snapcraft.io/build-snaps/metadata#0

3.2 ubuntu core 提供的interfaces

接下来一一介绍一些常用IO 口所使用的snap interface。

1) RTC:
你的snap app 中要读取RTC, 或者要调用hwclock 读取rtc , 需要两个接口:time-control & netlink-audit interface. 该slots 被core 提供, 你需要在app 的yaml 中申明plugs 使用这两个interface。

2) I2C, SPI, UART
这些接口,core 搜提供了对应的i2c, spi, serail interface , 你需要在app 的yaml 中申明plugs 使用对应的interface。

3) gpio
gpio 也需要interface, 才能访问;

4) SD/EMMC/Udisk
需要额外下载udisks2 snap 包,用以访问该设备上的文件,关于udisks2的描述可以参考如下链接:https://docs.ubuntu.com/core/en/stacks/disk/udisks2/docs/installation
设定udisk 的自动挂载, 使用下面命令:
snap set udisks2 automount.enable=true

5) watchdog
当前ubuntu core 没有提供interface 为watchdog,也就是你没有办法在strict 模式下,使用watchdog。不过你可以在安装时指定他为devmode, 这样让snap 包处在开发者模式下,使用watchdog, 当然也可以使用shell 命令来跳过这一限制。

4.安装流程

The Ubuntu Core install image is composed from the kernel, gadget, base, snapd and app snaps (see Snaps in Ubuntu Core for further details. The resultant image typically contains the following:
snap入门
Any device booting an Ubuntu Core 20 installation image will create or use the partitions defined by its Storage layout and proceed through the following installation steps.
A device image for an Ubuntu Core 20 device must only contain bootloader-specific partitions and ubuntu-seed, such that a recovery system in it can be booted into install mode. Installation will create and size the other missing partitions.
The definitive layout of the generated image used to install Ubuntu Core, and the resultant storage on the device, is described by the gadget snap and its associated gadget.yaml.

The first three (1-3) are also described in the recovery mode boot process:

  1. Boot through the bootloader, its assets, and boot configuration in ubuntu-seed.
  2. Bootloader loads the kernel from a designated recovery system.
  3. Kernel initialises the system and runs the snaps from that system in install mode. At this point, the system is running from tmpfs in an ephemeral state with all snaps from the recovery system model marked for use in install mode (as indicated by the modes field values), including the snapd snap, the gadget snap, the kernel snap and the base snap (usually the core20 snap).
  4. The snapd snap proceeds to install the actual run mode system by:
    • creating all missing partitions.
    • (optionally) encrypting ubuntu-data and ubuntu-save if supported and not disabled.
    • sealing the disk keys through hardware support.
    • setting up the run system in ubuntu-data.
    • setting boot configuration and the run mode kernel in ubuntu-boot for run mode.
  5. snapd proceeds to reboot into run mode.
  6. From run mode, snapd bootstraps itself and proceeds to seeding, installing and activating all the snaps marked for run mode use in the recovery system.

4.1 The install-device hook

A gadget can optionally define an install-device hook . This is invoked from install modebefore rebooting into run mode, between steps 4 and 5 above. All partitions are created and mounted when the install-device hook runs.
The install-device hook is executed with a fresh installation (rather than during a potential factory reset, for example), and can be used to perform early hardware and firmware configuration.

4.2 Factory image hint

A UC20 image can be built to include a hint that an image is intended to be used, or first booted, in the device factory. This hint can then be used to govern whether factory-only resources are accessible, for instance, but no security-related decisions should be made based solely on its inclusion as it could be possible for the hint to be set again in the field.

参考

https://elasticstack.blog.csdn.net/article/details/51886345

https://blog.csdn.net/UbuntuTouch/article/details/52312246

https://blog.csdn.net/changqing1990/article/details/82841830

https://ubuntu.com/core/docs/gadget-building
https://ubuntu.com/core/docs/uc20/installation-process
https://ubuntu.com/core/docs/board-enablement
https://ubuntu.com/core/docs/board-enablement#heading–image-building

上一篇:RK3399平台开发系列讲解(高速设备驱动篇)6.74、Gadget Driver (Legacy)


下一篇:usb测试