<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[BytesGuy's Blog]]></title><description><![CDATA[Join a seasoned Staff Software Engineer on a journey through CI/CD, automation, and cutting-edge hardware and software experimentation.]]></description><link>https://blog.bytesguy.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1700577906622/ZI_mzjHy1.png</url><title>BytesGuy&apos;s Blog</title><link>https://blog.bytesguy.com</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 18 May 2026 08:43:06 GMT</lastBuildDate><atom:link href="https://blog.bytesguy.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Installing Ubuntu Server on the StarFive VisionFive 2]]></title><description><![CDATA[In the evolving landscape of computer architectures, bringing familiar operating systems to new platforms presents a unique set of challenges. A recent endeavour of mine involved installing Ubuntu Server on the StarFive VisionFive 2 RISC-V board.
Unl...]]></description><link>https://blog.bytesguy.com/installing-ubuntu-server-starfive-visionfive-2-riscv</link><guid isPermaLink="true">https://blog.bytesguy.com/installing-ubuntu-server-starfive-visionfive-2-riscv</guid><category><![CDATA[risc-v]]></category><category><![CDATA[Ubuntu]]></category><category><![CDATA[uefi]]></category><category><![CDATA[Linux]]></category><category><![CDATA[ubuntu-server]]></category><dc:creator><![CDATA[Adam Hartley]]></dc:creator><pubDate>Sat, 25 Nov 2023 23:46:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1700694655035/9a0cd245-e7df-404c-8288-77a3fdfdc7d8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the evolving landscape of computer architectures, bringing familiar operating systems to new platforms presents a unique set of challenges. A recent endeavour of mine involved installing Ubuntu Server on the StarFive VisionFive 2 RISC-V board.</p>
<p>Unlike the straightforward installation process we're accustomed to with more mainstream architectures, this task required delving into the nuances of UEFI bootloader configurations and intricately managing the board's boot process.</p>
<p>This blog post is a deep dive into that journey, aiming to demystify the steps needed to achieve a stable and functional Ubuntu setup on this emerging architecture.</p>
<h3 id="heading-prerequisites">📋 Prerequisites</h3>
<p><strong>⚠️ Before you begin, your VisionFive 2 board will need to be running the latest firmware. For a guide on how to do this, check out</strong> <a target="_blank" href="https://blog.bytesguy.com/updating-u-boot-and-spl-on-the-starfive-visionfive-2"><strong>my previous blog post</strong></a> <strong>⚠️</strong></p>
<p>Hardware you will need:</p>
<ul>
<li><p>A MicroSD card (8GB+)</p>
</li>
<li><p>NVME SSD (installed on the underside of the VisionFive 2 board)</p>
</li>
<li><p>USB to UART dongle</p>
</li>
</ul>
<p>Files:</p>
<ul>
<li><a target="_blank" href="https://ubuntu.com/download/risc-v">Ubuntu Server Installer</a> (choose the StarFive VisionFive 2 option, then download the "live installer"</li>
</ul>
<h3 id="heading-board-setup">✅ Board Setup</h3>
<p>Flash the installer to the MicroSD card using <a target="_blank" href="http://etcher.balena.io/"><strong>Etcher</strong></a> and insert it into the MicroSD slot of the board.</p>
<p>Set the DIP switches to set the Boot Mode to <code>Flash</code></p>
<ul>
<li><p><code>RGPIO_1</code> -&gt; 0</p>
</li>
<li><p><code>RGPIO_0</code> -&gt; 0</p>
</li>
</ul>
<p>Finally, set up the UART to USB connection. I have been using the <a target="_blank" href="https://www.raspberrypi.com/products/debug-probe/">Raspberry Pi Debug Probe</a> which works great. Connect the UART leads to the board as follows:</p>
<ul>
<li><p>Pin 6 -&gt; <code>GND</code></p>
</li>
<li><p>Pin 8 -&gt; <code>RX</code></p>
</li>
<li><p>Pin 10 -&gt; <code>TX</code></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700567801091/022a1d58-ca59-4723-b0a3-b0309f800fc2.jpeg" alt="StarFive VisionFive2 Board With UART Connected" /></p>
<p>Next, you need to connect to the serial terminal. If you are using macOS for example, the serial device will show with a prefix of <code>tty.usbmodem</code>, so you can search for it with the command:</p>
<pre><code class="lang-plaintext">ls /dev | grep tty.usb
</code></pre>
<p>Then initialise a connection to it using <code>picocom</code>:</p>
<pre><code class="lang-bash">sudo picocom -b 115200 /dev/tty.usbmodem2112402
</code></pre>
<p>Now we are ready to install Ubuntu!</p>
<h3 id="heading-booting-the-ubuntu-installer">👢Booting the Ubuntu Installer</h3>
<p>To successfully boot the installer on the StarFive VisionFive 2 board, we must first identify the appropriate MicroSD Card and manually load essential files using U-Boot commands. Unlike more conventional systems where this process might be automated, the Ubuntu Installer for this specific RISC-V architecture requires direct intervention through the serial console. This step is crucial for initiating the installation process.</p>
<p>Firstly, power on the VisionFive board and interrupt the boot process when we see the following:</p>
<pre><code class="lang-plaintext">Hit any key to stop autoboot:  2
</code></pre>
<p>We start by listing all available memory cards with <code>mmc list</code> to see what options we have:</p>
<pre><code class="lang-plaintext">StarFive # mmc list
sdio0@16010000: 0
sdio1016020000: 1
</code></pre>
<p>In this case, we can see two devices listed; however, only one will be the MicroSD card with the installer on it. We can use the <code>part list</code> command to probe the device for partitions, and from there, determine which device and partition we need.</p>
<p>Let's examine the first device:</p>
<pre><code class="lang-plaintext">StarFive # part list mmc 0
Card did not respond to voltage select! : -110
</code></pre>
<p>Any time you see <code>Card did not respond to voltage select! : -110</code>, this generally means the device does not exist, or is not valid. So in this case we need to inspect the device with ID <code>1</code>:</p>
<pre><code class="lang-plaintext">StarFive # part list mmc 1

Partition Map for MMC device 1  --   Partition Type: EFI

Part    Start LBA    End LBA        Name
    Attributes
    Type GUID
    Partition GUID
  1    0x0000a000    0x0003efff    "EFI System"
    attrs:    0x0000000000000000
    type:    c12a7328-f81f-11d2-ba4b-00a0c93ec93b
    type:    system
    guid:    df2030ee-9281-40ba-8e38-027c9f37917e
  2    0x0003f000    0x0063efff    "Live Media"
    attrs:    0x0000000000000004
    type:    0fc63daf-8483-4772-8e79-3d69d8477de4
    type:    linux
    guid:    4b987a45-c7ad-4804-9048-717d7d37d6b0
  3    0x00000022    0x00000821    "loader1"
    attrs:    0x0000000000000000
    type:    5b193300-fc78-40cd-8002-e86c45580b47
    guid:    ad54bbfb-4527-4681-8f6e-fa7ef471109f
  4    0x00000822    0x00002821    "loader2"
    attrs:    0x0000000000000000
    type:    2e54b353-1271-4842-806f-e436d6af6985
    guid:    3a71d22e-655d-46a6-99db-66c67ea264a1
  5    0x0063f000    0x0e81f7ff    ""
    attrs:    0x0000000000000000
    type:    0fc63daf-8483-4772-8e79-3d69d8477de4
    type:    linux
    guid:    84bc9b76-b57e-4fa4-9367-cef404541690
</code></pre>
<p>We are looking for the <code>EFI System</code> partition, which in this case is partition number <code>1</code> of device <code>1</code></p>
<p>Next, we load a crucial hardware configuration file called the Device Tree Blob (DTB) from the the <code>EFI Partition</code> of the MicroSD Card (<code>mmc 1:1</code>) into the system's memory using the <code>load</code> command as below:</p>
<pre><code class="lang-plaintext">load mmc 1:1 $fdt_addr_r dtb/starfive/jh7110-starfive-visionfive-2-v1.3b.dtb
</code></pre>
<p>Following that, we also load the RISC-V Linux kernel, located in an EFI file, into memory using the <code>load</code> command:</p>
<pre><code class="lang-plaintext">load mmc 1:1 $kernel_addr_r EFI/boot/bootriscv64.efi
</code></pre>
<p>You will know the <code>load</code> command has run successfully if you see a message in the format of <code>12345 bytes read in 10 ms</code>.</p>
<p>Finally, we initiate the boot process with the <code>bootefi</code> command:</p>
<pre><code class="lang-plaintext">bootefi $kernel_addr_r $fdt_addr_r
</code></pre>
<p>This uses the loaded kernel and hardware configuration file to start up the installer. This sequence of commands essentially prepares the system and directs it to boot up from the specified files located on the memory card.</p>
<p>If successful, after a few seconds you should be greeted with the GRUB bootloader screen:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700952223671/61a7d2df-1b91-42ab-80ff-f4b587110a8d.png" alt="GRUB Bootloader" class="image--center mx-auto" /></p>
<p>Hit enter, or wait 30s, to proceed to the installer.</p>
<h3 id="heading-running-through-the-installer">⚙️ Running Through the Installer</h3>
<p>The installer can take a few minutes to run through the boot process and can, at times, appear to hang, but just let it run and it will eventually show you the following screen:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700952354089/90d568b3-66c5-4686-bc31-cfebffc0f851.png" alt="Ubuntu Installer via Serial" class="image--center mx-auto" /></p>
<p>From this menu, you can continue working with the installer via the serial console in either <code>rich</code> or <code>basic</code> mode. However, personally I found it easier, and more reliable, to use the SSH method. If you choose this method, you will be provided instructions on how to access the installer over SSH:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700952454094/16c99943-763d-46b1-ab13-a848c0633e4e.png" alt="Ubuntu Installer SSH Config" class="image--center mx-auto" /></p>
<p>Once you SSH in, you will see the standard Ubuntu Server installer program:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700952480394/0113e863-ea5d-4d36-8411-b1813fd79d70.png" alt="Ubuntu Installer" class="image--center mx-auto" /></p>
<p>The rest of the installer is the same as any other system, so work through it and configure the installation to your needs. Be sure to install Ubuntu on the NVME drive when prompted for the disk configuration - this will likely be the default option.</p>
<p>Once installed, let the device reboot automatically and move on to the final stage of configuring Ubuntu on the StarFive 2 board.</p>
<h3 id="heading-booting-ubuntu-on-nvme">🥾Booting Ubuntu on NVME</h3>
<p>Once the board reboots, you will likely be greeted with error messages in the serial console and Ubuntu will not boot automatically from the NVME drive:</p>
<pre><code class="lang-plaintext">Retrieving file: /extlinux/extlinux.conf
Can't set block device
Error reading config file
</code></pre>
<p>Don't panic, this is normal! In most systems, the Ubuntu installer will automatically configure UEFI variables to tell the bootloader how to boot into GRUB, however, U-Boot does not allow operating systems to configure these directly. So, we will have to do this manually.</p>
<p>Once the board has hit the error, it should drop you into the U-Boot prompt. From here you can run commands to boot Ubuntu manually:</p>
<pre><code class="lang-plaintext">pci enum
nvme scan
efidebug boot add -b 0001 'Ubuntu' nvme 0:1 /EFI/ubuntu/grubriscv64.efi
efidebug boot order 0001
bootefi bootmgr
</code></pre>
<p>We first enumerate the PCI devices on the board with <code>pci enum</code>, then we use <code>nvme scan</code> to identify and prepare any connected NVMe drives for use, allowing the system to recognize and interact with them.</p>
<p>Next, we need to add a UEFI boot entry with <code>efidebug boot add</code>. In this case, we are setting boot entry <code>1</code> and pointing it to the NVME drive with <code>nvme 0:1</code> and finally pointing it to the EFI executable <code>/EFI/ubuntu/grubriscv64.efi</code>.</p>
<p>We then set the boot order with <code>efidebug boot order</code> and then use <code>bootefi bootmgr</code> to boot the system using the UEFI boot manager. This will attempt to boot from the boot entries in the order they are set in the UEFI configuration, starting with the entry you specified (<code>0001</code> in this case).</p>
<h3 id="heading-getting-ubuntu-to-boot-automatically-from-nvme">🔄 Getting Ubuntu to Boot Automatically from NVME</h3>
<p>This above commands will boot Ubuntu fine every time, but this will not "stick" and the next time you boot the board you will face the same error and the OS will not load automatically. So just how do we achieve automatic boots?</p>
<p>Once again, we need to drop into the U-Boot console. This time we can set some UEFI environment variables to store the commands and run them automatically each time the board is booted:</p>
<pre><code class="lang-plaintext">env default -f -a
saveenv
setenv bootcmd_nvme0 "pci enum; nvme scan; efidebug boot add -b 0001 'Ubuntu' nvme 0:1 /EFI/ubuntu/grubriscv64.efi; efidebug boot order 0001; bootefi bootmgr"
setenv bootcmd 'run bootcmd_nvme0'
saveenv
</code></pre>
<p>First, we clear any existing variables to ensure a clean slate. Afterwards, we bundle the chain of commands into the <code>bootcmd_nvme0</code> variable for use later.</p>
<p>Then we point the <code>bootcmd</code> variable to run our custom boot command. The <code>bootcmd</code> variable defines the series of commands that U-Boot will automatically execute during the boot process. Essentially, it's the default action that U-Boot will take unless interrupted or directed otherwise.</p>
<p>Finally, save the variables and you are good to go!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700954910088/bd810b8d-d737-4213-a13c-1b339a569fd7.png" alt="Ubuntu Console on StarFive VisionFive 2 RISC-V Board" class="image--center mx-auto" /></p>
<p>The support for this board and RISC-V is still early for Ubuntu and certain things, such as HDMI output, may not be functional at the time of writing this. I suggest accessing the device through the serial console first, enabling SSH and going from there.</p>
<h3 id="heading-conclusion">🤔 Conclusion</h3>
<p>In summary, installing and running Ubuntu on the StarFive VisionFive 2 board is a journey through the intricacies of U-Boot/UEFI, highlighting the adaptability required when working with emerging architectures.</p>
<p>By manually configuring the UEFI boot process, we can successfully navigate these hurdles and get our favourite distros up and running. This process not only underscores the importance of a solid foundational understanding of system boot mechanisms but also opens the door to the vast potential of RISC-V boards in the world of Linux computing.</p>
<p>Have you ventured into installing operating systems on unconventional architectures like RISC-V? Do you have experiences, insights, or questions about running Ubuntu on the StarFive VisionFive 2 or similar boards? I’d love to hear about your journey and any challenges or triumphs you’ve encountered along the way. Feel free to share in the comments below or reach out to me on <a target="_blank" href="https://mastodon.social/@bytesguy">Mastodon</a>!</p>
]]></content:encoded></item><item><title><![CDATA[Updating U-Boot and SPL on the StarFive VisionFive 2]]></title><description><![CDATA[Ubuntu's recent foray into providing developer preview images for the emerging RISC-V architecture marks an exciting development for RISC-V enthusiasts. This is particularly true for those experimenting with popular supported development boards such ...]]></description><link>https://blog.bytesguy.com/updating-u-boot-and-spl-on-the-starfive-visionfive-2</link><guid isPermaLink="true">https://blog.bytesguy.com/updating-u-boot-and-spl-on-the-starfive-visionfive-2</guid><category><![CDATA[starfive]]></category><category><![CDATA[riscv]]></category><category><![CDATA[firmware]]></category><category><![CDATA[development]]></category><category><![CDATA[hardware]]></category><dc:creator><![CDATA[Adam Hartley]]></dc:creator><pubDate>Tue, 21 Nov 2023 12:28:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1700567734265/72f3fbe4-a8e1-400f-bfff-31180ff88d31.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ubuntu's recent foray into providing developer preview images for the emerging RISC-V architecture marks an exciting development for RISC-V enthusiasts. This is particularly true for those experimenting with popular supported development boards such as the StarFive VisionFive 2.</p>
<p>The prospect of running Ubuntu, or the latest Debian versions provided directly by StarFive, hinges critically on having the latest U-Boot and SPL firmware on these boards. However, working through the update process can be a challenge due to fragmented and sometimes confusing documentation.</p>
<p>So, if you are excited about running the latest operating systems on your VisionFive 2 board, then you are in the right place! In this post, I aim to demystify this process, offering a guide on updating your board's firmware through the most reliable methods, whether you're a seasoned tinkerer or a curious hobbyist exploring the potential of RISC-V architecture.</p>
<h2 id="heading-a-primer-on-u-boot-and-spl">🔍 A Primer on U-Boot and SPL</h2>
<p><em>Feel free to skip over this section if you are just here to update the firmware!</em></p>
<p>Before diving into the firmware update process, let's take a look at what U-Boot and SPL are and their roles in the VisionFive 2 board.</p>
<p>In the context of the VisionFive 2 board, U-Boot acts as the universal bootloader, a critical piece of software that orchestrates the booting process. It initialises the board's hardware, such as CPU and memory, and sets up the necessary environment for the OS to run. U-Boot is highly versatile, allowing for a variety of boot mediums and providing a rich set of commands for configuration and diagnostics via a serial console, making it an essential tool for developers.</p>
<p>Complementing U-Boot is the Secondary Program Loader (SPL), which is the minimalistic first-stage bootloader that takes action immediately after the board is powered on. The SPL's role is to perform the fundamental hardware initialisations and to prepare the system so that the more comprehensive U-Boot can take over the process.</p>
<p>This two-stage boot process ensures that the VisionFive 2 can handle the complex boot scenarios required by modern computing environments while maintaining the flexibility and robustness needed for the development and deployment of various applications on this RISC-V platform.</p>
<h2 id="heading-which-method-should-we-use">🤔 Which Method Should We Use?</h2>
<p>We will use the SD Card image method to update the board. While there are other methods to update the firmware, the SD Card image method is preferred due to its reliability and simplicity.</p>
<p>In most cases, if you have not updated the board's firmware, then the latest version of StarFive's Debian release, nor Ubuntu, will even boot in the first place.</p>
<p>You should also use this method if you are trying to use the <code>flashcp</code> command method and hit the <code>u-boot-spl.bin.normal.out won’t fit into /dev/mtd0!</code> error message.</p>
<h2 id="heading-prerequisites">📋 Prerequisites</h2>
<p>Hardware you will need:</p>
<ul>
<li><p>A MicroSD card (any size 1GB or more should work)</p>
</li>
<li><p>A USB flash drive</p>
</li>
<li><p>USB to UART dongle (optional, but required if you want to run Ubuntu later)</p>
</li>
</ul>
<p>Grab the latest version of the following files from the <a target="_blank" href="https://github.com/starfive-tech/VisionFive2/releases/">VisionFive2 Firmware Repo</a>:</p>
<ul>
<li><p><code>u-boot-spl.bin.normal.out</code> - put this on the USB flash drive</p>
</li>
<li><p><code>visionfive2_fw_payload.img</code> - put this on the USB flash drive</p>
</li>
<li><p><code>sdcard.img</code> - flash this to the MicroSD card using <a target="_blank" href="http://etcher.balena.io">Etcher</a></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700567809692/be10a580-38b2-4aaa-a7d7-43b0e4837c37.jpeg" alt /></p>
<h2 id="heading-hardware-setup">⚒️ Hardware Setup</h2>
<p>Set the DIP switches to set the Boot Mode to SDIO</p>
<ul>
<li><p><code>RGPIO_1</code> -&gt; 0</p>
</li>
<li><p><code>RGPIO_0</code> -&gt; 1</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700567818090/2dc1cc76-555a-4005-bc67-6e9b40be519a.jpeg" alt /></p>
<p>Install the MicroSD card you flashed earlier, plug the USB drive into any of the USB ports and ensure you have either an Ethernet network connection (for SSH) or HDMI and keyboard and mouse available.</p>
<p>Optionally, if you intend to use Ubuntu later, then you will need to set up the USB to UART device using the GPIO pins. I am using the rather handy <a target="_blank" href="https://www.raspberrypi.com/products/debug-probe/">Raspberry Pi Debug Probe</a> for this. The leads need to be connected from the board to your UART cable as follows:</p>
<ul>
<li><p>Pin 6 -&gt; <code>GND</code></p>
</li>
<li><p>Pin 8 -&gt; <code>RX</code></p>
</li>
<li><p>Pin 10 -&gt; <code>TX</code></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700567801091/022a1d58-ca59-4723-b0a3-b0309f800fc2.jpeg" alt /></p>
<h2 id="heading-updating-u-boot-and-spl">🔄 Updating U-Boot and SPL</h2>
<p>Power on the board and let it run through the boot process fully. This can take some time, but just let it run until you get a prompt. To run the commands following commands, you can either enter them directly or use SSH.</p>
<p>If you hit the dreaded <code>mipi_0p9: disabling</code> hang during the boot, you will need to SSH into the board as it is likely you are using a 4K monitor, which has been known to cause some issues. The username and password you need are <code>root</code> and <code>starfive</code>.</p>
<p>Next, we need to mount the USB drive so we can access the files. This is required as the image we are using right now is so minimal that it does not include any tools that will let us download the files or even a way to install them.</p>
<p>List the available disks with the <code>lsblk</code> command:</p>
<pre><code class="lang-plaintext"># lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda           8:0    1   116G  0 disk
|-sda1        8:1    1   200M  0 part
`-sda2        8:2    1 115.8G  0 part
</code></pre>
<p>In this case, sda2 is the drive and partition we need. Now we can mount the drive and access the files with:</p>
<pre><code class="lang-plaintext">mkdir usb
mount /dev/sda2 usb
</code></pre>
<p>Next, we need to list the MTD devices so we can be sure we are flashing the correct firmware to the correct device:</p>
<pre><code class="lang-plaintext"># cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00040000 00001000 "spl"
mtd1: 00010000 00001000 "uboot-env"
mtd2: 00300000 00001000 "uboot"
mtd3: 00100000 00001000 "data"
</code></pre>
<p>In this case, we need to flash the SPL firmware to <code>mtd0</code> and the U-Boot firmware to <code>mtd2</code>. This is done using the <code>flashcp</code> command and providing the files from the USB drive:</p>
<p>⚠️ Ensure you choose the correct device! ⚠️</p>
<pre><code class="lang-plaintext">cd usb
flashcp -v u-boot-spl.bin.normal.out /dev/mtd0
flashcp -v visionfive2_fw_payload.img /dev/mtd2
</code></pre>
<p>You should see output along the following lines if successful:</p>
<pre><code class="lang-plaintext"># cd usb
# flashcp -v u-boot-spl.bin.normal.out /dev/mtd0
Erasing blocks: 36/36 (100%)
Writing data: 143k/143k (100%)
Verifying data: 143k/143k (100%)
# flashcp -v visionfive2_fw_payload.img /dev/mtd2
Erasing blocks: 736/736 (100%)
Writing data: 2943k/2943k (100%)
Verifying data: 2943k/2943k (100%)
</code></pre>
<p>Now shut down the board and you are done updating the firmware!</p>
<h2 id="heading-preparing-for-ubuntu">👷 Preparing for Ubuntu</h2>
<p>If you want to run Ubuntu, there is an extra step and this is where the USB to UART bridge is required. After flashing the latest firmware, we need to reset the U-Boot environment variables to default values, otherwise, the installer/image will not boot.</p>
<p>To access the U-Boot console, you can use <code>picocom</code>. On macOS this can be installed with <code>brew install picocom</code>.</p>
<p>Next, find the USB to UART bridge device and connect to it. On macOS for example, these devices usually appear as <code>tty.usbmodem</code> devices, so look for it with the following command:</p>
<pre><code class="lang-plaintext">ls /dev | grep tty.usb
</code></pre>
<p>Then connect to it:</p>
<pre><code class="lang-bash">sudo picocom -b 115200 /dev/tty.usbmodem2112402
</code></pre>
<p>You should be greeted with <code>Terminal ready</code> if this was successful.</p>
<p>Next, power on the VisionFive 2 board. You will see a large amount of output, but for a few seconds you will have the chance to interrupt the boot process to allow us to drop into the U-Boot console:</p>
<pre><code class="lang-bash">Hit any key to stop autoboot:  2
</code></pre>
<p>Now you need to run the following commands:</p>
<pre><code class="lang-plaintext">env default -f -a
env save
</code></pre>
<p>The output should look like this:</p>
<pre><code class="lang-plaintext">StarFive # env default -f -a
## Resetting to default environment
StarFive # env save
Saving Environment to SPIFlash... 
Erasing SPI flash...
Writing to SPI flash...
done
OK
</code></pre>
<p>Shut down the board again and now you are prepared to run Ubuntu on your StarFive VisionFive 2 board! 🎉</p>
<h2 id="heading-round-up">📌 Round Up</h2>
<p>Now your StarFive VisionFive 2 board is fully updated and ready to run the latest operating systems! While the process is not very obvious from the official documentation, it is overall fairly simple once you get the hang of it. So, next time you need to update your board, simply follow the same steps as before and you will be up and running in no time.</p>
<p>For the next steps on running Ubuntu, visit the <a target="_blank" href="https://wiki.ubuntu.com/RISC-V/StarFive%20VisionFive%202">Ubuntu Documentation</a> to find out the different options for getting going with Ubuntu on this board.</p>
<p>Have fun!</p>
]]></content:encoded></item><item><title><![CDATA[Restoring Python 2 on macOS 12.3 and Higher]]></title><description><![CDATA[Just a very quick post today! I will be writing some more detailed posts about various topics soon, but things have been so busy over at CircleCI recently.
Apple recently released macOS 12.3 and, in the process, removed Python 2 from macOS entirely. ...]]></description><link>https://blog.bytesguy.com/restoring-python-2-on-macos-12</link><guid isPermaLink="true">https://blog.bytesguy.com/restoring-python-2-on-macos-12</guid><category><![CDATA[Python]]></category><category><![CDATA[macOS]]></category><dc:creator><![CDATA[Adam Hartley]]></dc:creator><pubDate>Thu, 14 Apr 2022 10:06:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649930731496/KjKsWCOgL.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Just a very quick post today! I will be writing some more detailed posts about various topics soon, but things have been so busy over at CircleCI recently.</p>
<p>Apple recently released macOS 12.3 and, in the process, removed Python 2 from macOS entirely. Python 2 has been deprecated, and EOL, for several years now (Homebrew deleted the formula some time ago), so the removal of it from the base OS is no real surprise.</p>
<p>As always, I would encourage everyone to migrate to Python 3 for better long-term support, but if you have scripts that absolutely must use Python 2, then this can be added back to macOS in a couple of commands.</p>
<h2 id="heading-adding-python-2-back-to-macos">Adding Python 2 back to macOS</h2>
<p>The Python project still hosts the final Python 2 macOS installer package, so we can simply download and install this to restore Python 2 to macOS. It is simple and quick to do this entirely from the command line:</p>
<pre><code class="lang-plaintext">curl -O https://www.python.org/ftp/python/2.7.18/python-2.7.18-macosx10.9.pkg
sudo installer -pkg python-2.7.18-macosx10.9.pkg -target /
</code></pre>
<p>Example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649929758417/k-2GSsL8m.png" alt="Screenshot 2022-04-14 at 10.49.13.png" /></p>
<p>It is as simple as that. Python 2 will now be available again via the <code>python</code> command and will live happily side by side with the system Python 3 installation (which is the <code>python3</code> command)</p>
<p>This also works in CircleCI, where Python 2 is no longer available from Xcode 13.3 onwards:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1649930005352/w1ZmhQKEf.png" alt="Screenshot 2022-04-14 at 10.53.22.png" /></p>
<p>Happy Building!</p>
]]></content:encoded></item><item><title><![CDATA[Resolving Let's Encrypt Issues with CURL on macOS]]></title><description><![CDATA[On 30 September, the DST Root CA X3 certificate, which Let's Encrypt were using to "cross-sign", expired. This root certificate was important as it allowed older clients to trust, relatively, new Let's Encrypt certificates which were also signed with...]]></description><link>https://blog.bytesguy.com/resolving-lets-encrypt-issues-with-curl-on-macos</link><guid isPermaLink="true">https://blog.bytesguy.com/resolving-lets-encrypt-issues-with-curl-on-macos</guid><category><![CDATA[macOS]]></category><category><![CDATA[ci-cd]]></category><dc:creator><![CDATA[Adam Hartley]]></dc:creator><pubDate>Tue, 05 Oct 2021 16:28:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633445677425/8WvdthYWW.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On 30 September, the DST Root CA X3 certificate, which Let's Encrypt were using to "cross-sign", expired. This root certificate was important as it allowed older clients to trust, relatively, new Let's Encrypt certificates which were also signed with their own root certificate (ISRG Root X1).</p>
<p>Now that the DST Root CA X3 root certificate has expired, clients that do not trust ISRG Root X1, now the only valid root for Let's Encrypt, will not be able to verify a Let's Encrypt SSL certificate is valid.</p>
<p>For most people, this is not a problem, as the <a target="_blank" href="https://letsencrypt.org/docs/certificate-compatibility/">supported platforms list</a> is fairly extensive and covers most modern platforms that end users will be using. In the case of macOS, this is supported from macOS 10.12.1 which was released in October 2016. However, if you use the <code>curl</code> command in macOS, you may find yourself hitting a roadblock, which can be especially problematic in a CI/CD environment.</p>
<h2 id="heading-the-problem">The Problem 🤔</h2>
<p>If you try to <code>curl</code> a website which is using a Let's Encrypt certificate, like Let's Encrypt's own homepage, you will find you receive the following error:</p>
<pre><code class="lang-plaintext">$ curl https://letsencrypt.org

curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Exited with code exit status 60
</code></pre>
<p>Yet if you open Safari and head to the same URL, there will be no problem at all! Why is this?</p>
<p>It appears that the default installation of <code>curl</code> in macOS does not use the default system keychain, or security framework, in macOS. The system keychain includes a copy of the new ISRG Root X1 certificate which allows any apps that use the security framework in macOS to trust Let's Encrypt SSL certificates. Therefore <code>curl</code> does not know this new certificate as it appears that Apple has not updated <code>curl</code>'s certificate store to add the ISRG Root X1 certificate - this only works out of the box in Big Sur and higher.</p>
<h2 id="heading-the-solution">The Solution 🙌</h2>
<p>Thankfully all is not lost! We can point <code>curl</code> to include an additional CA bundle to allow validation of Let's Encrypt certificates.</p>
<p>The curl project provides updated certificate stores every few months on <a target="_blank" href="https://curl.se/docs/caextract.html">their website</a>, so we can use this to resolve the error message seen above.</p>
<p>Firstly, we need to download the certificate bundle. You can either do this by heading to the <a target="_blank" href="https://curl.se/docs/caextract.html">download page</a>, or by using <code>curl</code>. It is important to note that if you use <code>curl</code>, you will need to use the <code>-k</code> option to skip validation of the SSL certificate as the curl project website also uses the ISRG Root X1 certificate - a chicken and the egg scenario 🐣!</p>
<pre><code class="lang-bash">curl -k https://curl.se/ca/cacert.pem -o ~/.cacert.pem
</code></pre>
<p>We then simply need to set <code>CURL_CA_BUNDLE</code> to the path of the new CA bundle which contains the ISRG Root X1 certificate. The easiest way to do this is to add it to your <code>.bash_profile</code>:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">'export CURL_CA_BUNDLE=~/.cacert.pem'</span> &gt;&gt; ~/.bash_profile
</code></pre>
<p>Now reload your shell, or <code>source ~/.bash_profile</code> and you will once again be able to use <code>curl</code> with any URL using Let's Encrypt!</p>
]]></content:encoded></item><item><title><![CDATA[Enabling Remote Automation in Safari 14+ via the Command Line]]></title><description><![CDATA[Apple is seemingly on a crusade to make working with their products and tools on the command line increasingly difficult. With each major version release, it appears that more and more useful "power user" features are disappearing, or becoming locked...]]></description><link>https://blog.bytesguy.com/enabling-remote-automation-in-safari-14</link><guid isPermaLink="true">https://blog.bytesguy.com/enabling-remote-automation-in-safari-14</guid><category><![CDATA[macOS]]></category><category><![CDATA[sysadmin]]></category><category><![CDATA[ci-cd]]></category><dc:creator><![CDATA[Adam Hartley]]></dc:creator><pubDate>Wed, 29 Sep 2021 10:47:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632495048280/rj3hCSZez.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Apple is seemingly on a crusade to make working with their products and tools on the command line increasingly difficult. With each major version release, it appears that more and more useful "power user" features are disappearing, or becoming locked away behind extra permissions.</p>
<p>For the vast majority of users, even developers, this is not an issue as who doesn't like extra security - simply click a few buttons instead and you'll be on your way. Yet little thought is given to headless environments, such as those used in continuous integration and delivery! CI/CD is a huge part of development lifecycles these days and with Apple removing useful features silently becoming a common occurrence, it is making setting up CI/CD pipelines harder than ever.</p>
<p>One such instance is the removal of the <code>AllowRemoteAutomation</code> key in Safari 14 and above. In the blog I discuss how I worked around this to provide our customers at CircleCI the ability to keep testing their websites with safaridriver in macOS Big Sur based images.</p>
<h2 id="heading-testing-with-safaridriver-on-safari-14">Testing with safaridriver on Safari 14+ 🖥</h2>
<p>It is essential that the <code>AllowRemoteAutomation</code> key is set to <code>true</code> before safaridriver is enabled, otherwise remote control of Safari is not possible.</p>
<p>In Safari 13 and lower, on CircleCI we could typically set up a job as follows:</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">defaults</span> <span class="hljs-string">write</span> <span class="hljs-string">com.apple.Safari</span> <span class="hljs-string">AllowRemoteAutomation</span> <span class="hljs-number">1</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">sudo</span> <span class="hljs-string">safaridriver</span> <span class="hljs-string">--enable</span>
</code></pre>
<p>This was all that was needed to set up the environment ready for Selenium tests.</p>
<p>However, try this on a CircleCI image that provides Safari 14 (such as the Xcode 12.5 image based on macOS Big Sur) and you will be treated with the following error message:</p>
<pre><code class="lang-text">SessionNotCreatedError: Could not create a session: You must enable the 'Allow Remote Automation' option in Safari's Develop menu to control Safari via WebDriver.
</code></pre>
<p>Turns out Apple silently removed this key, along with <code>IncludeDevelopMenu</code> and <code>IncludeDebugMenu</code> - all of which were very useful in headless environments! There is seemingly no replacement for these either, so you are now forced to enable them with the GUI. This is also true in Safari 15 on macOS Monterey.</p>
<p><img src="https://media.giphy.com/media/zrdUjl6N99nLq/giphy.gif?cid=ecf05e47j0nbhnd725l9dchkdlkywy1ulj2vmgsr9wtnokdf&amp;rid=giphy.gif&amp;ct=g" alt="How it feels to be a Mac person working in DevOps" /></p>
<p><em>Above: How it feels to be a Mac person working in DevOps (🐼=🍎)</em></p>
<h2 id="heading-applescript-to-the-rescue">AppleScript to the Rescue! 🍎📝</h2>
<p>Thankfully all is not lost as we can employ AppleScript to interact with the GUI for us and enable options we need. AppleScript is a powerful tool for automating actions in macOS, although to get it running in a CI/CD environment</p>
<pre><code class="lang-plaintext">tell application "System Events"
    tell application "Safari" to activate
    delay 5

    tell process "Safari"
        set frontmost to true
        click menu item "Preferences…" of menu 1 of menu bar item "Safari" of menu bar 1
        click button "Advanced" of toolbar 1 of window 1
        tell checkbox "Show Develop menu in menu bar" of group 1 of group 1 of window 1
            if value is 0 then click it
        end tell
        click button 1 of window 1
        click menu item "Allow Remote Automation" of menu 1 of menu bar item "Develop" of menu bar 1
    end tell
end tell
</code></pre>
<p>(You'll have to forgive the formatting here as Hashnode does not know what AppleScript is!)</p>
<p>This script, while it may not look pretty, achieves the same result as toggling the <code>AllowRemoteAutomation</code> key by working with the GUI in Safari to toggle the same option.</p>
<p>Firstly, we need to open Safari and ensure it is brought to the foreground to prevent any potential hiccups when the rest of the script tries to run.</p>
<p>Next we open Safari's preferences, head over to the "Advanced" section and toggle the "Show Develop menu in menu bar" option. This places Safari in Developer mode, equivalent to toggling the <code>IncludeDevelopMenu</code> flag in Safari 13 and lower.</p>
<p>Finally, the script toggles the "Allow Remote Automation" option in the "Develop" menu.</p>
<p>Phew! Now while this works locally (simply throw it into Script Editor and run it), there are more things to consider when getting it to run within the CircleCI macOS environment...</p>
<h2 id="heading-getting-it-to-work-on-circleci">Getting it to Work on CircleCI 🤔</h2>
<p>While running the above AppleScript locally, you may have noticed a permission pop-up occur. If you do not grant this permission, then the AppleScript will not be able to interact with Safari. As the CircleCI environment is headless and non-interactive, this poses a big problem as, surprise 🎉, there is no command line equivalent for accepting/adding permissions.</p>
<p>Working with permissions in the CircleCI macOS environment is a whole blog post by itself, so I will not go into depth here (stay tuned for that post in the future). The short story is that we can manually inject the correct permissions into the permissions database (SQLite-based). This emulates what the permissions GUI does, but is only possible if System Integrity Protection is disabled.</p>
<p>Finally, this needs to be made easy for customers to set up. No one wants to copy and paste a bunch of complex <code>sqlite3</code> commands and add the AppleScript as a file in their repo. This is where <a target="_blank" href="https://circleci.com/developer/orbs">Orbs</a> come in. We can package these commands up into a tidy, single line call to the Orb. By using the <code>osascript -e</code> command we can keep the AppleScript in-line to the Orb as well!</p>
<p>For the full source code, check out the <code>add-safari-permissions</code> command in the <a target="_blank" href="https://circleci.com/developer/orbs/orb/circleci/macos#commands-add-safari-permissions">macOS Orb</a>.</p>
<h2 id="heading-summary">Summary</h2>
<p>Well that's it for this blog post, I hope it was helpful!</p>
<p>While Safari is a small drop in the ocean compared to Chrome, with <a target="_blank" href="https://gs.statcounter.com/browser-market-share/desktop/worldwide">10% market share</a>, it is still important that developers are able to test against it with ease in their CircleCI pipelines with a bit of AppleScript magic.</p>
<p>I will be writing more about how we have worked around Apple's weirdness in future posts, so please stay tuned.</p>
]]></content:encoded></item></channel></rss>