IBM Power S822LC(8335-GTB) BMC 升级

背景 最近拿到一台 IBM Power S822LC(8335-GTB) 机器的访问权限,这也是我第一次碰 ppc64le 指令集的服务器。然后发现,它的 BMC 版本比较老,我想连接 Remote Control 失败了,原因是 JViewer 不支持 macOS,我就想着能不能升级一下。 升级过程 首先,在网上找了一下文档,首先用 ipmitool 找一下机器型号: $ sudo ipmitool fru print 3 Chassis Type : Unknown Chassis Part Number : 8335-GTB Chassis Serial : REDACTED 可以看到,这台机器是 8335-GTB 型号,按照这个型号在 Fix Central 上搜索,可以找到若干个版本的 firmware,其中最老的版本是 OP8_v1.11_2.1,对比了一下,和原来的版本一致: $ sudo ipmitool fru print 47 Product Name : OpenPOWER Firmware Product Version : IBM-garrison-ibm-OP8_v1.11_2.1 Product Extra : op-build-da02863 Product Extra : buildroot-81b8d98 Product Extra : skiboot-5.

Read More

在 arm64 上使用 rust-analyzer

远程到 arm64 的机器上进行开发,发现没有 rust-analyzer 的支持。研究了一下,发现在 rustup 里面可以找到,不过要配置一下: > rustup toolchain add nightly > rustup component add --toolchain nightly rust-analyzer-preview 这个时候,应该可以找到 ~/.rustup/toolchains/nightly-aarch64-unknown-linux-gnu/bin/rust-analyzer 文件,接下来,配置 VSCode 插件即可: { "rust-analyzer.serverPath": "~/.rustup/toolchains/nightly-aarch64-unknown-linux-gnu/bin/rust-analyzer" } 路径在 ~/.vscode-server/data/Machine/settings.json。 参考:https://github.com/rust-analyzer/rust-analyzer/issues/5256

Read More

在 Rpi4 上运行 buildroot

背景 需要给 rpi 配置一个 pxe 的最小环境,在上一篇博文了提到可以用 alpine,但发现有一些不好用的地方,所以试了试 buildroot。 PXE 设置和路由器设置 见 “在 Rpi4 上运行 Alpine Linux” 文章。 Buildroot 配置 下载 buildroot : > wget https://buildroot.org/downloads/buildroot-2020.08.tar.gz > unar buildroot-2020.08.tar.gz > cd buildroot-2020.08 > make raspberrypi4_64_defconfig 然后运行 make menuconfig ,在 Filesystem images 中打开 initramfs ,并设置 cpio 压缩为 gz 。然后直接编译: > make -j4 $ ls -al target/images bcm2711-rpi-4-b.dtb* boot.vfat Image rootfs.cpio rootfs.cpio.gz rootfs.ext2 rootfs.ext4@ rpi-firmware/ sdcard.img 接着,在一个单独的目录里,把这些文件整理一下 > cd ~/rpi-buildroot > cp -r ~/buildroot-2020.

Read More

在 rpi4 上用 PXE 运行 Alpine Linux

背景 需要给 rpi 配置一个 pxe 的最小环境,然后看到 alpine 有 rpi 的支持,所以尝试给 rpi4 配置 alpine 。 PXE 设置 第一步是设置 rpi4 的启动模式,打开 BOOT UART 并且打开 网络启动: > cd /lib/firmware/raspberrypi/bootloader/critical > rpi-eeprom-config pieeprom-2020-04-16.bin > config.txt $ cat config.txt [all] BOOT_UART=1 WAKE_ON_GPIO=1 POWER_OFF_ON_HALT=0 DHCP_TIMEOUT=45000 DHCP_REQ_TIMEOUT=4000 TFTP_FILE_TIMEOUT=30000 TFTP_IP= TFTP_PREFIX=0 BOOT_ORDER=0x12 SD_BOOT_MAX_RETRIES=3 NET_BOOT_MAX_RETRIES=5 [none] FREEZE_VERSION=0 > sed 's/BOOT_UART=0/BOOT_UART=1/;s/BOOT_ORDER=0x1/BOOR_ORDER=0x21/' config.txt > config-pxe.txt > rpi-eeprom-config --out pieeprom-2020-04-16-pxe.bin --config config-pxe.txt pieeprom-2020-04-16.bin > rpi-eeprom-update -d -f pieeprom-2020-04-16.pxe.bin > reboot 重启以后,可以用 vcgencmd bootloader_config 查看当前的启动配置,看是否正确地更新了启动配置。比较重要的是 BOOT_ORDER,0x21 表示先尝试网络启动,再尝试 SD 卡启动。

Read More

用 certbot 申请 route53 上的域名的 LetsEncrypt 证书并上传到 IAM

最近遇到了 AWS Certificate Manager 的一些限制,所以只能用 IAM 证书。于是上网找到了通过 certbot 申请 LE 证书,通过 route53 API 验证的方法。 首先配置 aws 的 credential。然后,按照 certbot: pip3 install -U certbot certbot_dns_route53 然后,就可以申请证书了: certbot certonly --dns-route53 --config-dir "./letsencrypt" --work-dir "./letsencrypt" --logs-dir "./letsencrypt" -d example.com --email a@b.com --agree-tos 如果申请成功,在当前目录下可以找到证书。然后上传到 IAM: aws iam upload-server-certificate --server-certificate-name NameHere \ --certificate-body file://letsencrypt/live/example.com/cert.pem \ --private-key file://letsencrypt/live/example.com/privkey.pem \ --certificate-chain file://letsencrypt/live/example.com/chain.pem \ --path /cloudfront/ 如果要用于 cloudfront,才需要最后的路径参数;否则可以去掉。这样就完成了 IAM 证书的上传。

Read More

在 k8s 中部署 Prometheus

实验了一下在 k8s 中部署 Prometheus,因为它和 k8s 有比较好的集成,很多 App 能在 k8s 里通过 service discovery 被 Prometheus 找到并且抓取数据。实践了一下,其实很简单。 用 helm 进行配置: helm upgrade --install prometheus stable/prometheus 这样就可以了,如果已经有 StorageClass (比如腾讯云的话,CBS 和 CFS),它就能自己起来了,然后在 Lens 里面也可以看到各种 metrics 的可视化。 如果是自建的单结点的 k8s 集群,那么还需要自己创造 PV,并且把 PVC 绑定上去。我采用的是 local 类型的 PV: apiVersion: v1 kind: PersistentVolume metadata: name: pv-volume-1 labels: type: local spec: storageClassName: manual capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: "/srv/k8s-data-1" --- apiVersion: v1 kind: PersistentVolume metadata: name: pv-volume-2 labels: type: local spec: storageClassName: manual capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: "/srv/k8s-data-2" 这样,结点上的两个路径分别对应两个 PV,然后只要让 PVC 也用 manual 的 StorageClass 就可以了:

Read More

各种 ecc 曲线

背景知识 椭圆曲线有如下的形式: 第一种: $$E: y^2 \equiv x^3 + ax + b \mod{p}$$ 曲线的参数共有 \((p, a, b, G, n, h)\)。\(G\) 是一个点 \((G_x, G_y)\),\(n\) 是 \(G\) 的阶。 第二种: $$E: y^2+xy=x^3+ax^2+1$$ 称为 Kbolitz curve。不同的曲线有不同的参数 \((m,f(x),a,b,G,n,h)\),对应不同的 \(GF(2^m)\) 域。 OpenSSL 看一下 openssl 支持的曲线参数(openssl ecparam -list_curves): secp112r1 : SECG/WTLS curve over a 112 bit prime field secp112r2 : SECG curve over a 112 bit prime field secp128r1 : SECG curve over a 128 bit prime field secp128r2 : SECG curve over a 128 bit prime field secp160k1 : SECG curve over a 160 bit prime field secp160r1 : SECG curve over a 160 bit prime field secp160r2 : SECG/WTLS curve over a 160 bit prime field secp192k1 : SECG curve over a 192 bit prime field secp224k1 : SECG curve over a 224 bit prime field secp224r1 : NIST/SECG curve over a 224 bit prime field secp256k1 : SECG curve over a 256 bit prime field secp384r1 : NIST/SECG curve over a 384 bit prime field secp521r1 : NIST/SECG curve over a 521 bit prime field prime192v1: NIST/X9.

Read More

FIDO U2F、FIDO2 和 CTAP 的关系

背景 2012 年,Yubico 和 Google 设计了 U2F 协议,第二年 U2F 成为 FIDO 组织的标准,之后加入了 NFC 的支持。之后,FIDO2 作为替代 U2F 的新标准产生,原来的 U2F 以兼容的方式成为了 CTAP1,而采用 CBOR 封装格式的 CTAP(CTAP2) 则是 FIDO2 的主要协议。 U2F 命令格式 U2F 定义了它的命令格式,基于 ISO7816-4 APDU(short APDU) : CLA INS P1 P2 Lc data Le 1 byte 1 byte 1 byte 1 byte 0-1 bytes variable length 0-1 bytes 比如 U2F_VERSION 就是: CLA INS P1 P2 Lc data Le 00 03 00 00 0 empty 00 返回的数据就是 U2F_V2 的 ASCII 加上 9000 的状态。

Read More

USB/IP 模拟 USB 设备

背景 2018 年的时候发过一篇博客,讲如何用 USB/IP 协议在两台 Linux 电脑之间共享 USB 设备。最近刚好有一个需求,就是针对一个现成的 USB device 的代码,通过 USB/IP 模拟出一个 USB 设备,然后进行调试。 USB/IP 协议 USB/IP 只有一个简略的文档,为数不多的使用 USB/IP 的代码,所以有一些细节没有说的很清楚,只能一点点去尝试。 首先,USB/IP 基于 TCP,端口号 3240 。客户端向服务端发送请求,服务端向客户端进行回应。 请求的类型:OP_REQ_DEVLIST OP_REQ_IMPORT USBIP_CMD_SUBMIT 和 USBIP_CMD_UNLINK 回应的类型:OP_REP_DEVLIST OP_REP_IMPORT USBIP_RET_SUBMIT USBIP_RET_UNLINK 工作的过程大概如下: OP_REQ_DEVLIST 请求获取设备列表 OP_REP_DEVLIST 返回设备列表 OP_REQ_IMPORT 请求 USB 设备 OP_REP_IMPORT 返回 USB 设备 USBIP_CMD_SUBMIT 发送 URB USBIP_RET_SUBMIT 返回 URB (先不考虑 CMD_UNLINK 和 RET_UNLINK) 其中前面四个比较简单清晰,所需要的字段也都是 Descriptor 中对应的字段。后面两个就相对复杂一些:URB data 的长度需要根据 endpoint 类型和 direction 共同决定。URB 实际上是 Linux 内核里的一个数据结构。

Read More

MIFARE Classic 上配置 NDEF

背景 最近买了一堆 NFC 的智能卡拿来测试,其中一张 MIFARE Classic 的总是在 iOS 上读不出来,无论是以 Tag 模式还是 NDEF 模式。于是通过一系列的研究,终于知道上怎么一回事,然后成功地把一个 MIFARE Classic 卡配置成了 NDEF。 背景知识 NFC 有很多协议,其中 MIFARE Classic 基于 ISO 14443-3 Type A 标准,里面有一些 MIFARE 的命令。通过这些命令,就可以控制 MIFARE Classic 卡的内容。具体来说,以我使用的 MIFARE Classic EV1 4K S70 为例,这篇文章会涉及到如下的背景知识: MIFARE Classic 内存布局 在 MIFARE Classic 中,有 Sector 和 Block 的概念,每个 Sector 有若干个 Block,其中最后一个 Block 是特殊的(称为 Sector Trailer),保存了这个 Sector 的一些信息:Key A、Access Bits、GPB 和 Key B。对于 Classic 4K,首先是 32 个有 4 blocks 的 sector,然后是 8 个 有 16 blocks 的 sector, 整体的内存布局大概是:

Read More