<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alpinelinux.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fission</id>
	<title>Alpine Linux - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alpinelinux.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fission"/>
	<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/wiki/Special:Contributions/Fission"/>
	<updated>2026-05-05T20:14:16Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=XDG_RUNTIME_DIR&amp;diff=32352</id>
		<title>XDG RUNTIME DIR</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=XDG_RUNTIME_DIR&amp;diff=32352"/>
		<updated>2026-04-30T12:16:21Z</updated>

		<summary type="html">&lt;p&gt;Fission: Fix broken hyperlink&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Various daemons and applications depend on the &amp;lt;code&amp;gt;XDG_RUNTIME_DIR&amp;lt;/code&amp;gt; environment variable being set, including [[Wayland]], [[PipeWire]] and others. This variable should point to a private, ephemeral directory owned by the current user. The exact semantics and details for this variable (and the directory to which it points) are documented in the [https://specifications.freedesktop.org/basedir/latest/#variables XDG base directory specification].&lt;br /&gt;
&lt;br /&gt;
A few mechanisms exist to properly initialise this variable and its corresponding directory, as described below. Only one should be used for a user&#039;s session; configuring multiple of these mechanisms will lead to misbehaviours.&lt;br /&gt;
&lt;br /&gt;
== Initialising via elogind ==&lt;br /&gt;
&lt;br /&gt;
When using [[elogind]] as a seat manager, it exports &amp;lt;code&amp;gt;XDG_RUNTIME_DIR&amp;lt;/code&amp;gt; and other XDG environment variables automatically for each session. No further configuration is required. &amp;lt;code&amp;gt;XDG_RUNTIME_DIR&amp;lt;/code&amp;gt; would be set as {{Path|/run/user/$(id -u)}} by &#039;&#039;&#039;elogind&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Initialising via pam_rundir ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/jjk-jacky/pam_rundir pam_rundir] is a [[PAM]] module that provides the runtime directory variable. Installing the package {{pkg|pam-rundir}} takes care of dependencies and no further configuration is required. &amp;lt;code&amp;gt;XDG_RUNTIME_DIR&amp;lt;/code&amp;gt; would be set as  {{Path|/run/user/$(id -u)}} by pam_rundir.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/ifreund/dumb_runtime_dir dumb_runtime_dir] is functionally equivalent and has cleaner, simpler code, but is not currently packaged in Alpine.&lt;br /&gt;
&lt;br /&gt;
== Initialising via mkrundir ==&lt;br /&gt;
&lt;br /&gt;
[https://git.sr.ht/~whynothugo/mkrundir mkrundir] is an executable that can be used to initialise the runtime directory explicitly by each user. To use &amp;lt;code&amp;gt;mkrundir&amp;lt;/Code&amp;gt;, install the package {{pkg|mkrundir}} available in [[Repositories#Testing|testing]] repository. The path to &amp;lt;code&amp;gt;XDG_RUNTIME_DIR&amp;lt;/code&amp;gt; is printed by mkrundir.  A shell init script (e.g.: {{Path|~/.profile}} must include an entry as follows at the &#039;&#039;&#039;top&#039;&#039;&#039; of the file {{Cat|~/.profile|...&lt;br /&gt;
export XDG_RUNTIME_DIR{{=}}$(mkrundir)&lt;br /&gt;
...}}&lt;br /&gt;
&lt;br /&gt;
See the journal entry [https://whynothugo.nl/journal/2026/04/02/creating-an-xdg_runtime_dir/ Creating an XDG_RUNTIME_DIR] for background on its design.&lt;br /&gt;
&lt;br /&gt;
== Initialising manually in /tmp ==&lt;br /&gt;
&lt;br /&gt;
Generally, care should be taken when configuring the &amp;lt;code&amp;gt;XDG_*&amp;lt;/code&amp;gt; variables manually as this configuration may have errors or conflict with other utilities that do this automatically. Use this only on a system that&#039;s not using [[elogind]] and other solutions outlined above cannot handle this. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XDG_RUNTIME_DIR&amp;lt;/code&amp;gt; can be initialised manually by adding below snippet to shell init scripts (e.g.: {{Path|~/.profile}}):&lt;br /&gt;
&lt;br /&gt;
{{Cat|~/.profile|&amp;lt;nowiki&amp;gt;if test -z &amp;quot;${XDG_RUNTIME_DIR}&amp;quot;; then&lt;br /&gt;
  export XDG_RUNTIME_DIR=/tmp/xdg/&amp;quot;${UID}&amp;quot;-xdg-runtime-dir&lt;br /&gt;
    if ! test -d &amp;quot;${XDG_RUNTIME_DIR}&amp;quot;; then&lt;br /&gt;
      mkdir -p &amp;quot;${XDG_RUNTIME_DIR}&amp;quot;&lt;br /&gt;
      chmod 0700 &amp;quot;${XDG_RUNTIME_DIR}&amp;quot;&lt;br /&gt;
    fi&lt;br /&gt;
fi &lt;br /&gt;
&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* An overview of different approaches for [https://whynothugo.nl/journal/2026/04/02/creating-an-xdg_runtime_dir/ creating an XDG_RUNTIME_DIR]&lt;/div&gt;</summary>
		<author><name>Fission</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Talk:Riscv64&amp;diff=32178</id>
		<title>Talk:Riscv64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Talk:Riscv64&amp;diff=32178"/>
		<updated>2026-03-25T21:30:24Z</updated>

		<summary type="html">&lt;p&gt;Fission: Sure, why not&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Can we move to host implementation targeted sub-pages? ==&lt;br /&gt;
There&#039;s a lot of information here regarding QEMU based installation which is fantastic for getting off the ground.  There are a lot of specifics regarding different RISCV64 processors and boards though.  This page could quickly get muddied with information for SiFive, Allwinner, SpacemiT, etc.  My thought is that the current contents of this page become sub-page and the main Riscv64 page reference the different types of installation targets.&lt;br /&gt;
: Sure! I can see that this page is already long enough with just the QEMU content, so I’m happy to see it separated into its own page, as long as we can leave a “breadcrumb” from this main [[Riscv64]] page to the new one. Thanks! [[User:Fission|Fission]] ([[User talk:Fission|talk]]) 21:30, 25 March 2026 (UTC)&lt;/div&gt;</summary>
		<author><name>Fission</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Riscv64&amp;diff=32176</id>
		<title>Riscv64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Riscv64&amp;diff=32176"/>
		<updated>2026-03-25T19:31:42Z</updated>

		<summary type="html">&lt;p&gt;Fission: Be consistent about the riscv64 name; move the extlinux.conf warning closer to where it will be used&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
&lt;br /&gt;
riscv64 (RISC-V 64-bit) is one of the [[architecture|architectures]] that Alpine Linux supports. The first stable release was Alpine Linux 3.20. Standard ISO images are available since Alpine Linux 3.23. You can download it from the [https://alpinelinux.org/downloads/ Alpine Linux downloads] page.&lt;br /&gt;
&lt;br /&gt;
== Running Alpine riscv64 in QEMU ==&lt;br /&gt;
&lt;br /&gt;
=== Installing QEMU on Alpine ===&lt;br /&gt;
&lt;br /&gt;
Installing QEMU for RISC-V on Alpine is very straightforward:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# apk add qemu-system-riscv64 qemu-img}}&lt;br /&gt;
&lt;br /&gt;
You will need {{Pkg|qemu-img|arch=riscv64}} if you want to create QCOW2 disk images; if you only want to create raw images, it’s not needed.&lt;br /&gt;
&lt;br /&gt;
For example, to create a new 2&amp;amp;nbsp;GB QCOW2 disk image:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-img create -f qcow2 alpine-riscv64.qcow2 2G}}&lt;br /&gt;
&lt;br /&gt;
Adjust the &#039;&#039;size&#039;&#039; parameter as you see fit.&lt;br /&gt;
&lt;br /&gt;
=== Getting U-Boot ===&lt;br /&gt;
&lt;br /&gt;
[https://u-boot.org/ U-Boot], aka &#039;&#039;Das U-Boot: The Universal Boot Loader&#039;&#039;, is one of the easiest, most flexible ways to boot Alpine on RISC-V. It can be used with GRUB for EFI booting, or with &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt; for non-EFI booting.&lt;br /&gt;
&lt;br /&gt;
You need the file &#039;&#039;&#039;&amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt;&#039;&#039;&#039; to boot using U-Boot. Alpine provides a compiled &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; in two places:&lt;br /&gt;
&lt;br /&gt;
# The &#039;&#039;&#039;Generic U-Boot tarball&#039;&#039;&#039; on the [https://alpinelinux.org/downloads/ Alpine downloads page]. Currently that is:&lt;br /&gt;
#:https://dl-cdn.alpinelinux.org/alpine/v3.23/releases/riscv64/alpine-uboot-3.23.3-riscv64.tar.gz&lt;br /&gt;
# The &#039;&#039;&#039;[https://pkgs.alpinelinux.org/package/edge/main/riscv64/u-boot-qemu &amp;lt;code&amp;gt;u-boot-qemu&amp;lt;/code&amp;gt; package for &amp;lt;code&amp;gt;riscv64&amp;lt;/code&amp;gt;]&#039;&#039;&#039;. Note that if you are not already on an Alpine riscv64 system, you won’t be able to just &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; this package, as it will be for a different architecture. In practical terms this means downloading the &amp;lt;code&amp;gt;.apk&amp;lt;/code&amp;gt; file directly from an APK mirror, e.g.:&lt;br /&gt;
#:https://dl-cdn.alpinelinux.org/edge/main/riscv64/u-boot-qemu-2026.01-r0.apk&lt;br /&gt;
&lt;br /&gt;
If you downloaded the &amp;lt;code&amp;gt;.tgz&amp;lt;/code&amp;gt; file, this command will extract the &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; file to the current directory:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ tar --strip-components 3 -xf alpine-uboot-3.23.3-riscv64.tar.gz \&lt;br /&gt;
    ./u-boot/qemu-riscv64_smode/u-boot.bin}}&lt;br /&gt;
&lt;br /&gt;
If you downloaded the &amp;lt;code&amp;gt;.apk&amp;lt;/code&amp;gt; file, this command will extract the &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; file to the current directory:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ tar --strip-components 4 -xf u-boot-qemu-2026.01-r0.apk \&lt;br /&gt;
    usr/share/u-boot/qemu-riscv64_smode/u-boot.bin}}&lt;br /&gt;
&lt;br /&gt;
{{Note|There are two &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; files, but you need the one in the &amp;lt;code&amp;gt;qemu-riscv64_smode&amp;lt;/code&amp;gt; directory. That is because OpenSBI (the first thing QEMU executes) will run in &#039;&#039;M-mode&#039;&#039; (the highest privilege), which expects to execute U-Boot in &#039;&#039;S-mode&#039;&#039; (one privilege level lower).}}&lt;br /&gt;
&lt;br /&gt;
=== U-Boot + GRUB EFI ===&lt;br /&gt;
&lt;br /&gt;
The easiest way to run Alpine riscv64 in EFI mode is to boot from the ISO. You can download it from the [https://alpinelinux.org/downloads/ Alpine downloads page]. Here is an example of launching QEMU using U-Boot to boot this ISO:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel u-boot.bin \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}cd0}}&lt;br /&gt;
&lt;br /&gt;
The boot path is therefore:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; U-Boot =&amp;gt; GRUB EFI =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* &amp;lt;code&amp;gt;-kernel u-boot.bin&amp;lt;/code&amp;gt; is what causes OpenSBI to load U-Boot.&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* The ISO is being treated as a &amp;lt;code&amp;gt;virtio-blk-device&amp;lt;/code&amp;gt; rather than a real CD-ROM drive.&lt;br /&gt;
* After you’ve run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt;, you can remove the last two lines on subsequent launches so the ISO is no longer attached.&lt;br /&gt;
&lt;br /&gt;
It’s equally possible to boot using just the Generic U-Boot tarball. First, it needs to be fully extracted, &#039;&#039;except&#039;&#039; &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt;, which U-Boot will try to use first if present:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ mkdir alpine-uboot-3.23.3-riscv64&lt;br /&gt;
$ tar -C alpine-uboot-3.23.3-riscv64 --exclude ./extlinux/extlinux.conf \&lt;br /&gt;
    -xf alpine-uboot-3.23.3-riscv64.tar.gz}}&lt;br /&gt;
&lt;br /&gt;
Then you can launch QEMU and have it emulate the &amp;lt;code&amp;gt;alpine-uboot-3.23.3-riscv64&amp;lt;/code&amp;gt; as a [https://www.qemu.org/docs/master/system/images.html#virtual-fat-disk-images Virtual FAT disk image]:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel u-boot.bin \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd1}}&lt;br /&gt;
&lt;br /&gt;
This is nearly identical to the previous command, except the change from the ISO to the extracted tarball directory (&amp;lt;code&amp;gt;alpine-uboot-3.23.3-riscv64&amp;lt;/code&amp;gt;). Note the &amp;lt;code&amp;gt;fat:ro:&amp;lt;/code&amp;gt; syntax to emulate a virtual hard drive from a directory on the host.&lt;br /&gt;
&lt;br /&gt;
=== U-Boot + extlinux.conf ===&lt;br /&gt;
&lt;br /&gt;
U-Boot can use &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt; to boot, which does not require EFI (and therefore does not use GRUB).&lt;br /&gt;
&lt;br /&gt;
The simplest way to boot without EFI is to use the Generic U-Boot tarball. In this case, it’s extracted without modification and booted as a [https://www.qemu.org/docs/master/system/images.html#virtual-fat-disk-images Virtual FAT disk image].&lt;br /&gt;
&lt;br /&gt;
First, extract the Generic U-Boot tarball:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ mkdir alpine-uboot-3.23.3-riscv64&lt;br /&gt;
$ tar -C alpine-uboot-3.23.3-riscv64 -xf alpine-uboot-3.23.3-riscv64.tar.gz}}&lt;br /&gt;
&lt;br /&gt;
Then, launch QEMU:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel u-boot.bin \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}fat:ro:alpine-uboot-3.23.3-riscv64,if{{=}}none,id{{=}}hd1,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd1}}&lt;br /&gt;
&lt;br /&gt;
{{Warning|A [https://lists.denx.de/pipermail/u-boot/2025-August/596500.html regression exists in U-Boot 2025.10], which is included with the Alpine 3.23 release, that may prevent booting via &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt;. The error will be similar to:&lt;br /&gt;
&lt;br /&gt;
    Failed to reserve memory for fdt at 0xbee9e220&lt;br /&gt;
    FDT creation failed! hanging...### ERROR ### Please RESET the board ###&lt;br /&gt;
&lt;br /&gt;
This has been [https://github.com/u-boot/u-boot/commit/62f1afbe7a8ae8f8b9e85c5ea4eb446b97892a7c resolved in U-Boot 2026.01].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solution:&#039;&#039;&#039; use the &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; file from the Alpine Edge build of the {{Pkg|u-boot-qemu|arch=riscv64}} package, which will be U-Boot 2026.01 or later. See the &#039;&#039;[[#Getting_U-Boot|Getting U-Boot]]&#039;&#039; section for the URL and APK extraction instructions.}}&lt;br /&gt;
&lt;br /&gt;
The boot path is therefore:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; U-Boot + extlinux.conf =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* &amp;lt;code&amp;gt;-kernel u-boot.bin&amp;lt;/code&amp;gt; is what causes OpenSBI to load U-Boot.&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* After you’ve run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt;, you can remove the last two lines on subsequent launches, so the virtual FAT disk image is no longer attached.&lt;br /&gt;
&lt;br /&gt;
{{Tip|You may see a usage message that begins like:&lt;br /&gt;
&lt;br /&gt;
    usage: /usr/sbin/update-u-boot [-b{{!}}--board &amp;lt;board-type&amp;gt;] [-d{{!}}--device &amp;lt;device&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This is harmless. If it concerns you, it can be suppressed during the install by using the &amp;lt;code&amp;gt;BOOTLOADER&amp;lt;/code&amp;gt; environment variable:&lt;br /&gt;
&lt;br /&gt;
    {{Cmd|# BOOTLOADER{{=}}none setup-alpine}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
(While it is technically possible to install from the ISO using &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt;, doing so is more trouble than it’s worth, as you have to create a separate boot volume containing &amp;lt;code&amp;gt;/boot/vmlinuz-lts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/boot/initramfs-lts&amp;lt;/code&amp;gt; from the ISO, and &amp;lt;code&amp;gt;/extlinux/extlinux.conf&amp;lt;/code&amp;gt; from the Generic U-Boot tarball.)&lt;br /&gt;
&lt;br /&gt;
=== EDK2 + GRUB EFI ===&lt;br /&gt;
&lt;br /&gt;
Using EDK2 is convenient in that it comes bundled with {{Pkg|qemu-system-riscv64|arch=riscv64}}. However, it does require a few more QEMU options than U-Boot to work successfully.&lt;br /&gt;
&lt;br /&gt;
Here is an example using EDK2 to boot the Alpine riscv64 standard ISO:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ cp /usr/share/qemu/edk2-riscv-vars.fd .&lt;br /&gt;
$ qemu-system-riscv64 -machine virt,acpi{{=}}off -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -drive if{{=}}pflash,format{{=}}raw,unit{{=}}0,file{{=}}/usr/share/qemu/edk2-riscv-code.fd,readonly{{=}}on \&lt;br /&gt;
    -drive if{{=}}pflash,format{{=}}raw,unit{{=}}1,file{{=}}edk2-riscv-vars.fd \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}cd0}}&lt;br /&gt;
&lt;br /&gt;
{{Warning|EDK2 will not boot the kernel without &amp;lt;code&amp;gt;acpi{{=}}off&amp;lt;/code&amp;gt;. It could be that the ACPI data QEMU is providing EDK2 is not compatible or accurate, somehow.}}&lt;br /&gt;
&lt;br /&gt;
The boot path is:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; EDK2 =&amp;gt; GRUB EFI =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* The two &amp;lt;code&amp;gt;pflash&amp;lt;/code&amp;gt; lines load two files:&lt;br /&gt;
** the EDK2 &#039;&#039;code&#039;&#039; in &amp;lt;code&amp;gt;readonly&amp;lt;/code&amp;gt; mode.&lt;br /&gt;
** the EDK2 &#039;&#039;vars&#039;&#039; (EDK2’s nvram, essentially) in a writable way.&lt;br /&gt;
**:(EDK2 doesn’t load via &amp;lt;code&amp;gt;-kernel&amp;lt;/code&amp;gt;, unlike U-Boot.)&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* After you’ve run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt;, you can remove the last two lines on subsequent launches, so the virtual FAT disk image is no longer attached.&lt;br /&gt;
&lt;br /&gt;
{{Tip|EDK2 produces &#039;&#039;voluminous&#039;&#039; output before the Linux kernel starts. This is expected, even if seemingly abnormal.}}&lt;br /&gt;
&lt;br /&gt;
=== Direct booting ===&lt;br /&gt;
&lt;br /&gt;
“Direct” booting means using QEMU to load the kernel and initramfs files into memory and having OpenSBI boot them directly, bypassing any other bootloader such as U-Boot, EDK2, GRUB, etc. This is a very fast method of booting, but there are some points to consider:&lt;br /&gt;
&lt;br /&gt;
* You will have to somehow get the kernel and initramfs onto the host system. During installation, this is straightforward enough: you can extract them out of the installation media. But for subsequent boots (ie, after &amp;lt;code&amp;gt;apk upgrade&amp;lt;/code&amp;gt; has changed the kernel or initramfs in the guest), this becomes more challenging.&lt;br /&gt;
* Reboots will not use a new kernel from within the guest (ie, one downloaded via &amp;lt;code&amp;gt;apk upgrade&amp;lt;/code&amp;gt;), but the one that was present on the host when QEMU was first launched. For this reason, it’s suggested that you use the &amp;lt;code&amp;gt;-noreboot&amp;lt;/code&amp;gt; QEMU option to prevent reboots.&lt;br /&gt;
* Because there is no bootloader to pass kernel options, you must specify &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; QEMU options instead. Fortunately these are rather standardized.&lt;br /&gt;
&lt;br /&gt;
The boot path for this method is simply:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
==== Extracting the images ====&lt;br /&gt;
&lt;br /&gt;
To make extracting the images easier, here is a shell function you can use. It uses 7-Zip, which you can install on Alpine with &amp;lt;code&amp;gt;apk add {{Pkg|7zip|arch=riscv64}}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Cat|extract.sh|extract_boot_images() {&lt;br /&gt;
    case &amp;quot;$1&amp;quot; in&lt;br /&gt;
        iso{{!}}tar)&lt;br /&gt;
            7z x -aoa &amp;quot;$2&amp;quot; boot/vmlinuz-lts boot/initramfs-lts&lt;br /&gt;
            ;;&lt;br /&gt;
        hdimg)&lt;br /&gt;
            7z x -aoa &amp;quot;$2&amp;quot; 0.img&lt;br /&gt;
            7z x -aoa 0.img -oboot vmlinuz-lts initramfs-lts&lt;br /&gt;
            rm -f 0.img&lt;br /&gt;
            ;;&lt;br /&gt;
    esac&lt;br /&gt;
    [ -f boot/vmlinuz-lts ] &amp;amp;&amp;amp; gunzip &amp;lt; boot/vmlinuz-lts &amp;gt; boot/vmlinux-lts&lt;br /&gt;
&amp;amp;#125;}}&lt;br /&gt;
&lt;br /&gt;
This function takes two arguments: the file type, &amp;lt;code&amp;gt;iso&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;hdimg&amp;lt;/code&amp;gt;, and the filename itself.&lt;br /&gt;
&lt;br /&gt;
For the Alpine ISO or Generic U-Boot tarball, the extraction is fairly straightforward. For hard drive images (either QCOW2 or raw), it will extract the first partition (which ought to be &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt;, ie, &amp;lt;code&amp;gt;/dev/vda1&amp;lt;/code&amp;gt;), and then extract the images from that. In both cases, it decompresses &amp;lt;code&amp;gt;vmlinuz-lts&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;vmlinux-lts&amp;lt;/code&amp;gt;, since it seems that OpenSBI wants an uncompressed kernel image.&lt;br /&gt;
&lt;br /&gt;
{{Note|If you extract the kernel and initramfs from the ISO, you should use the ISO to install; and similarly, if you extract them from the Generic U-Boot tarball, you should use the tarball to install.}}&lt;br /&gt;
&lt;br /&gt;
==== Install booting ====&lt;br /&gt;
&lt;br /&gt;
Here is an example QEMU command line for installation booting (first using the shell script above to extract the images):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ . extract.sh&lt;br /&gt;
$ extract_boot_images iso alpine-standard-3.23.3-riscv64.iso&lt;br /&gt;
$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel boot/vmlinux-lts \&lt;br /&gt;
    -initrd boot/initramfs-lts \&lt;br /&gt;
    -append &amp;quot;modules{{=}}loop,squashfs,sd-mod,usb-storage quiet&amp;quot; \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-scsi-device,id{{=}}scsi0 \&lt;br /&gt;
    -device scsi-cd,drive{{=}}cd0,bus{{=}}scsi0.0 \&lt;br /&gt;
    -noreboot}}&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* The &amp;lt;code&amp;gt;-kernel&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;-initrd&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; lines set up the kernel boot from files on the host. The &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; string is set up for booting from install media (the ISO or tarball).&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* &amp;lt;code&amp;gt;-noreboot&amp;lt;/code&amp;gt; prevents the system from rebooting back into the installer. (You should change the command post installation so that subsequent launches boot from your hard drive image.)&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt; as normal. It may attempt to install a bootloader, but it won’t be used.&lt;br /&gt;
&lt;br /&gt;
==== Normal booting ====&lt;br /&gt;
&lt;br /&gt;
After the installation, you can run a normal boot by extracting the kernel and initramfs out of the hard drive image you just created:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ . extract.sh&lt;br /&gt;
$ extract_boot_images hdimg alpine-riscv64.qcow2&lt;br /&gt;
$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel boot/vmlinux-lts \&lt;br /&gt;
    -initrd boot/initramfs-lts \&lt;br /&gt;
    -append &amp;quot;root{{=}}/dev/vda3 modules{{=}}sd-mod,usb-storage,ext4 quiet rootfstype{{=}}ext4&amp;quot;&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -noreboot}}&lt;br /&gt;
&lt;br /&gt;
The main difference here is in the image extraction (done using the hard drive image rather than the installation media) and in the &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; line, which specifies the virtio disk &amp;lt;code&amp;gt;/dev/vda3&amp;lt;/code&amp;gt; as the &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Normally the &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; parameter would be a UUID. If you prefer to use a UUID, you can grab it using a command like:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# blkid /dev/vda3}}&lt;br /&gt;
&lt;br /&gt;
And update your &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; parameter accordingly, e.g.:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|    -append &amp;quot;root{{=}}UUID{{=}}2341d7cd-e050-427e-afff-94fa0db4c8c5 modules{{=}}sd-mod,usb-storage,ext4 quiet rootfstype{{=}}ext4&amp;quot; \}}&lt;br /&gt;
&lt;br /&gt;
=== Using apk to create an image ===&lt;br /&gt;
&lt;br /&gt;
Yet another way to create a hard drive image for Alpine riscv64 would be with the help of an existing Alpine system (using any architecture, not just riscv64). Here are two articles that discuss this method:&lt;br /&gt;
&lt;br /&gt;
* [https://arvanta.net/alpine/install-alpine-riscv64-qemu/ install Alpine Linux riscv64 under qemu]&lt;br /&gt;
* [https://arvanta.net/alpine/install-alpine-riscv64-qemu-uboot/ install Alpine Linux riscv64 under qemu with u-boot loader]&lt;br /&gt;
&lt;br /&gt;
{{Note|These articles were created for a previous version of Alpine, and there may be differences in the way that a current &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt; deploys a new system &#039;&#039;vs&#039;&#039; the result from these scripts. However, the techniques used are still sound and may be of interest.}}&lt;br /&gt;
&lt;br /&gt;
== Contribute ==&lt;br /&gt;
* Test out the port and [https://gitlab.alpinelinux.org/alpine/aports/-/issues/?label_name%5B%5D=arch%3Ariscv64 report] the bugs you find.&lt;br /&gt;
* Write and improve guides about the port.&lt;br /&gt;
* Fix [https://gitlab.alpinelinux.org/alpine/aports packages] that are buggy or don&#039;t work on RISC-V.&lt;br /&gt;
&#039;&#039;This section is based on [https://irclogs.alpinelinux.org/%23alpine-riscv64-2025-10.log this] [[Alpine Linux:IRC|IRC]] conversation from 2025-10-01.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Riscv64]]&lt;/div&gt;</summary>
		<author><name>Fission</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Riscv64&amp;diff=32175</id>
		<title>Riscv64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Riscv64&amp;diff=32175"/>
		<updated>2026-03-25T10:36:09Z</updated>

		<summary type="html">&lt;p&gt;Fission: Fixing template-breaking character escaping&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
&lt;br /&gt;
RISC-V 64 is one of the [[architecture|architectures]] that Alpine Linux supports. The first stable release was Alpine Linux 3.20. Standard ISO images are available since Alpine Linux 3.23. You can download it from the [https://alpinelinux.org/downloads/ Alpine Linux downloads] page.&lt;br /&gt;
&lt;br /&gt;
== Running Alpine RISC-V 64 in QEMU ==&lt;br /&gt;
&lt;br /&gt;
=== Installing QEMU on Alpine ===&lt;br /&gt;
&lt;br /&gt;
Installing QEMU for RISC-V&amp;amp;nbsp;64 on Alpine is very straightforward:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# apk add qemu-system-riscv64 qemu-img}}&lt;br /&gt;
&lt;br /&gt;
You will need {{Pkg|qemu-img|arch=riscv64}} if you want to create QCOW2 disk images; if you only want to create raw images, it’s not needed.&lt;br /&gt;
&lt;br /&gt;
For example, to create a new 2&amp;amp;nbsp;GB QCOW2 disk image:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-img create -f qcow2 alpine-riscv64.qcow2 2G}}&lt;br /&gt;
&lt;br /&gt;
Adjust the &#039;&#039;size&#039;&#039; parameter as you see fit.&lt;br /&gt;
&lt;br /&gt;
=== Getting U-Boot ===&lt;br /&gt;
&lt;br /&gt;
[https://u-boot.org/ U-Boot], aka &#039;&#039;Das U-Boot: The Universal Boot Loader&#039;&#039;, is one of the easiest, most flexible ways to boot Alpine on RISC-V&amp;amp;nbsp;64. It can be used with GRUB for EFI booting, or with &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt; for non-EFI booting.&lt;br /&gt;
&lt;br /&gt;
You need the file &#039;&#039;&#039;&amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt;&#039;&#039;&#039; to boot using U-Boot. Alpine provides a compiled &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; in two places:&lt;br /&gt;
&lt;br /&gt;
# The &#039;&#039;&#039;Generic U-Boot tarball&#039;&#039;&#039; on the [https://alpinelinux.org/downloads/ Alpine downloads page]. Currently that is:&lt;br /&gt;
#:https://dl-cdn.alpinelinux.org/alpine/v3.23/releases/riscv64/alpine-uboot-3.23.3-riscv64.tar.gz&lt;br /&gt;
# The &#039;&#039;&#039;[https://pkgs.alpinelinux.org/package/edge/main/riscv64/u-boot-qemu &amp;lt;code&amp;gt;u-boot-qemu&amp;lt;/code&amp;gt; package for &amp;lt;code&amp;gt;riscv64&amp;lt;/code&amp;gt;]&#039;&#039;&#039;. Note that if you are not already on an Alpine riscv64 system, you won’t be able to just &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; this package, as it will be for a different architecture. In practical terms this means downloading the &amp;lt;code&amp;gt;.apk&amp;lt;/code&amp;gt; file directly from an APK mirror, e.g.:&lt;br /&gt;
#:https://dl-cdn.alpinelinux.org/edge/main/riscv64/u-boot-qemu-2026.01-r0.apk&lt;br /&gt;
&lt;br /&gt;
If you downloaded the &amp;lt;code&amp;gt;.tgz&amp;lt;/code&amp;gt; file, this command will extract the &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; file to the current directory:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ tar --strip-components 3 -xf alpine-uboot-3.23.3-riscv64.tar.gz \&lt;br /&gt;
    ./u-boot/qemu-riscv64_smode/u-boot.bin}}&lt;br /&gt;
&lt;br /&gt;
If you downloaded the &amp;lt;code&amp;gt;.apk&amp;lt;/code&amp;gt; file, this command will extract the &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; file to the current directory:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ tar --strip-components 4 -xf u-boot-qemu-2026.01-r0.apk \&lt;br /&gt;
    usr/share/u-boot/qemu-riscv64_smode/u-boot.bin}}&lt;br /&gt;
&lt;br /&gt;
{{Note|There are two &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; files, but you need the one in the &amp;lt;code&amp;gt;qemu-riscv64_smode&amp;lt;/code&amp;gt; directory. That is because OpenSBI (the first thing QEMU executes) will run in &#039;&#039;M-mode&#039;&#039; (the highest privilege), which expects to execute U-Boot in &#039;&#039;S-mode&#039;&#039; (one privilege level lower).}}&lt;br /&gt;
&lt;br /&gt;
{{Warning|A [https://lists.denx.de/pipermail/u-boot/2025-August/596500.html regression exists in U-Boot 2025.10], which is included with the Alpine 3.23 release, that may prevent booting via &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt;. The error will be similar to:&lt;br /&gt;
&lt;br /&gt;
    Failed to reserve memory for fdt at 0xbee9e220&lt;br /&gt;
    FDT creation failed! hanging...### ERROR ### Please RESET the board ###&lt;br /&gt;
&lt;br /&gt;
This has been [https://github.com/u-boot/u-boot/commit/62f1afbe7a8ae8f8b9e85c5ea4eb446b97892a7c resolved in U-Boot 2026.01].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solution:&#039;&#039;&#039; use the &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; file from Alpine Edge (URL given above) APK file that has version 2026.01 or later.}}&lt;br /&gt;
&lt;br /&gt;
=== U-Boot + GRUB EFI ===&lt;br /&gt;
&lt;br /&gt;
The easiest way to run Alpine riscv64 in EFI mode is to boot from the ISO. You can download it from the [https://alpinelinux.org/downloads/ Alpine downloads page]. Here is an example of launching QEMU using U-Boot to boot this ISO:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel u-boot.bin \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}cd0}}&lt;br /&gt;
&lt;br /&gt;
The boot path is therefore:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; U-Boot =&amp;gt; GRUB EFI =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* &amp;lt;code&amp;gt;-kernel u-boot.bin&amp;lt;/code&amp;gt; is what causes OpenSBI to load U-Boot.&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* The ISO is being treated as a &amp;lt;code&amp;gt;virtio-blk-device&amp;lt;/code&amp;gt; rather than a real CD-ROM drive.&lt;br /&gt;
* After you’ve run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt;, you can remove the last two lines on subsequent launches so the ISO is no longer attached.&lt;br /&gt;
&lt;br /&gt;
It’s equally possible to boot using just the Generic U-Boot tarball. First, it needs to be fully extracted, &#039;&#039;except&#039;&#039; &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt;, which U-Boot will try to use first if present:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ mkdir alpine-uboot-3.23.3-riscv64&lt;br /&gt;
$ tar -C alpine-uboot-3.23.3-riscv64 --exclude ./extlinux/extlinux.conf \&lt;br /&gt;
    -xf alpine-uboot-3.23.3-riscv64.tar.gz}}&lt;br /&gt;
&lt;br /&gt;
Then you can launch QEMU and have it emulate the &amp;lt;code&amp;gt;alpine-uboot-3.23.3-riscv64&amp;lt;/code&amp;gt; as a [https://www.qemu.org/docs/master/system/images.html#virtual-fat-disk-images Virtual FAT disk image]:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel u-boot.bin \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd1}}&lt;br /&gt;
&lt;br /&gt;
This is nearly identical to the previous command, except the change from the ISO to the extracted tarball directory (&amp;lt;code&amp;gt;alpine-uboot-3.23.3-riscv64&amp;lt;/code&amp;gt;). Note the &amp;lt;code&amp;gt;fat:ro:&amp;lt;/code&amp;gt; syntax to emulate a virtual hard drive from a directory on the host.&lt;br /&gt;
&lt;br /&gt;
=== U-Boot + extlinux.conf ===&lt;br /&gt;
&lt;br /&gt;
U-Boot can use &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt; to boot, which does not require EFI (and therefore does not use GRUB).&lt;br /&gt;
&lt;br /&gt;
The simplest way to boot without EFI is to use the Generic U-Boot tarball. In this case, it’s extracted without modification and booted as a [https://www.qemu.org/docs/master/system/images.html#virtual-fat-disk-images Virtual FAT disk image].&lt;br /&gt;
&lt;br /&gt;
First, extract the Generic U-Boot tarball:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ mkdir alpine-uboot-3.23.3-riscv64&lt;br /&gt;
$ tar -C alpine-uboot-3.23.3-riscv64 -xf alpine-uboot-3.23.3-riscv64.tar.gz}}&lt;br /&gt;
&lt;br /&gt;
Then, launch QEMU:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel u-boot.bin \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}fat:ro:alpine-uboot-3.23.3-riscv64,if{{=}}none,id{{=}}hd1,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd1}}&lt;br /&gt;
&lt;br /&gt;
The boot path is therefore:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; U-Boot + extlinux.conf =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* &amp;lt;code&amp;gt;-kernel u-boot.bin&amp;lt;/code&amp;gt; is what causes OpenSBI to load U-Boot.&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* After you’ve run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt;, you can remove the last two lines on subsequent launches, so the virtual FAT disk image is no longer attached.&lt;br /&gt;
&lt;br /&gt;
{{Tip|You may see a usage message that begins like:&lt;br /&gt;
&lt;br /&gt;
    usage: /usr/sbin/update-u-boot [-b{{!}}--board &amp;lt;board-type&amp;gt;] [-d{{!}}--device &amp;lt;device&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This is harmless. If it concerns you, it can be suppressed during the install by using the &amp;lt;code&amp;gt;BOOTLOADER&amp;lt;/code&amp;gt; environment variable:&lt;br /&gt;
&lt;br /&gt;
    {{Cmd|# BOOTLOADER{{=}}none setup-alpine}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
(While it is technically possible to install from the ISO using &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt;, doing so is more trouble than it’s worth, as you have to create a separate boot volume containing &amp;lt;code&amp;gt;/boot/vmlinuz-lts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/boot/initramfs-lts&amp;lt;/code&amp;gt; from the ISO, and &amp;lt;code&amp;gt;/extlinux/extlinux.conf&amp;lt;/code&amp;gt; from the Generic U-Boot tarball.)&lt;br /&gt;
&lt;br /&gt;
=== EDK2 + GRUB EFI ===&lt;br /&gt;
&lt;br /&gt;
Using EDK2 is convenient in that it comes bundled with {{Pkg|qemu-system-riscv64|arch=riscv64}}. However, it does require a few more QEMU options than U-Boot to work successfully.&lt;br /&gt;
&lt;br /&gt;
Here is an example using EDK2 to boot the Alpine riscv64 standard ISO:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ cp /usr/share/qemu/edk2-riscv-vars.fd .&lt;br /&gt;
$ qemu-system-riscv64 -machine virt,acpi{{=}}off -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -drive if{{=}}pflash,format{{=}}raw,unit{{=}}0,file{{=}}/usr/share/qemu/edk2-riscv-code.fd,readonly{{=}}on \&lt;br /&gt;
    -drive if{{=}}pflash,format{{=}}raw,unit{{=}}1,file{{=}}edk2-riscv-vars.fd \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}cd0}}&lt;br /&gt;
&lt;br /&gt;
{{Warning|EDK2 will not boot the kernel without &amp;lt;code&amp;gt;acpi{{=}}off&amp;lt;/code&amp;gt;. It could be that the ACPI data QEMU is providing EDK2 is not compatible or accurate, somehow.}}&lt;br /&gt;
&lt;br /&gt;
The boot path is:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; EDK2 =&amp;gt; GRUB EFI =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* The two &amp;lt;code&amp;gt;pflash&amp;lt;/code&amp;gt; lines load two files:&lt;br /&gt;
** the EDK2 &#039;&#039;code&#039;&#039; in &amp;lt;code&amp;gt;readonly&amp;lt;/code&amp;gt; mode.&lt;br /&gt;
** the EDK2 &#039;&#039;vars&#039;&#039; (EDK2’s nvram, essentially) in a writable way.&lt;br /&gt;
**:(EDK2 doesn’t load via &amp;lt;code&amp;gt;-kernel&amp;lt;/code&amp;gt;, unlike U-Boot.)&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* After you’ve run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt;, you can remove the last two lines on subsequent launches, so the virtual FAT disk image is no longer attached.&lt;br /&gt;
&lt;br /&gt;
{{Tip|EDK2 produces &#039;&#039;voluminous&#039;&#039; output before the Linux kernel starts. This is expected, even if seemingly abnormal.}}&lt;br /&gt;
&lt;br /&gt;
=== Direct booting ===&lt;br /&gt;
&lt;br /&gt;
“Direct” booting means using QEMU to load the kernel and initramfs files into memory and having OpenSBI boot them directly, bypassing any other bootloader such as U-Boot, EDK2, GRUB, etc. This is a very fast method of booting, but there are some points to consider:&lt;br /&gt;
&lt;br /&gt;
* You will have to somehow get the kernel and initramfs onto the host system. During installation, this is straightforward enough: you can extract them out of the installation media. But for subsequent boots (ie, after &amp;lt;code&amp;gt;apk upgrade&amp;lt;/code&amp;gt; has changed the kernel or initramfs in the guest), this becomes more challenging.&lt;br /&gt;
* Reboots will not use a new kernel from within the guest (ie, one downloaded via &amp;lt;code&amp;gt;apk upgrade&amp;lt;/code&amp;gt;), but the one that was present on the host when QEMU was first launched. For this reason, it’s suggested that you use the &amp;lt;code&amp;gt;-noreboot&amp;lt;/code&amp;gt; QEMU option to prevent reboots.&lt;br /&gt;
* Because there is no bootloader to pass kernel options, you must specify &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; QEMU options instead. Fortunately these are rather standardized.&lt;br /&gt;
&lt;br /&gt;
The boot path for this method is simply:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
==== Extracting the images ====&lt;br /&gt;
&lt;br /&gt;
To make extracting the images easier, here is a shell function you can use. It uses 7-Zip, which you can install on Alpine with &amp;lt;code&amp;gt;apk add {{Pkg|7zip|arch=riscv64}}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Cat|extract.sh|extract_boot_images() {&lt;br /&gt;
    case &amp;quot;$1&amp;quot; in&lt;br /&gt;
        iso{{!}}tar)&lt;br /&gt;
            7z x -aoa &amp;quot;$2&amp;quot; boot/vmlinuz-lts boot/initramfs-lts&lt;br /&gt;
            ;;&lt;br /&gt;
        hdimg)&lt;br /&gt;
            7z x -aoa &amp;quot;$2&amp;quot; 0.img&lt;br /&gt;
            7z x -aoa 0.img -oboot vmlinuz-lts initramfs-lts&lt;br /&gt;
            rm -f 0.img&lt;br /&gt;
            ;;&lt;br /&gt;
    esac&lt;br /&gt;
    [ -f boot/vmlinuz-lts ] &amp;amp;&amp;amp; gunzip &amp;lt; boot/vmlinuz-lts &amp;gt; boot/vmlinux-lts&lt;br /&gt;
&amp;amp;#125;}}&lt;br /&gt;
&lt;br /&gt;
This function takes two arguments: the file type, &amp;lt;code&amp;gt;iso&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;hdimg&amp;lt;/code&amp;gt;, and the filename itself.&lt;br /&gt;
&lt;br /&gt;
For the Alpine ISO or Generic U-Boot tarball, the extraction is fairly straightforward. For hard drive images (either QCOW2 or raw), it will extract the first partition (which ought to be &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt;, ie, &amp;lt;code&amp;gt;/dev/vda1&amp;lt;/code&amp;gt;), and then extract the images from that. In both cases, it decompresses &amp;lt;code&amp;gt;vmlinuz-lts&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;vmlinux-lts&amp;lt;/code&amp;gt;, since it seems that OpenSBI wants an uncompressed kernel image.&lt;br /&gt;
&lt;br /&gt;
{{Note|If you extract the kernel and initramfs from the ISO, you should use the ISO to install; and similarly, if you extract them from the Generic U-Boot tarball, you should use the tarball to install.}}&lt;br /&gt;
&lt;br /&gt;
==== Install booting ====&lt;br /&gt;
&lt;br /&gt;
Here is an example QEMU command line for installation booting (first using the shell script above to extract the images):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ . extract.sh&lt;br /&gt;
$ extract_boot_images iso alpine-standard-3.23.3-riscv64.iso&lt;br /&gt;
$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel boot/vmlinux-lts \&lt;br /&gt;
    -initrd boot/initramfs-lts \&lt;br /&gt;
    -append &amp;quot;modules{{=}}loop,squashfs,sd-mod,usb-storage quiet&amp;quot; \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-scsi-device,id{{=}}scsi0 \&lt;br /&gt;
    -device scsi-cd,drive{{=}}cd0,bus{{=}}scsi0.0 \&lt;br /&gt;
    -noreboot}}&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* The &amp;lt;code&amp;gt;-kernel&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;-initrd&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; lines set up the kernel boot from files on the host. The &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; string is set up for booting from install media (the ISO or tarball).&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* &amp;lt;code&amp;gt;-noreboot&amp;lt;/code&amp;gt; prevents the system from rebooting back into the installer. (You should change the command post installation so that subsequent launches boot from your hard drive image.)&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt; as normal. It may attempt to install a bootloader, but it won’t be used.&lt;br /&gt;
&lt;br /&gt;
==== Normal booting ====&lt;br /&gt;
&lt;br /&gt;
After the installation, you can run a normal boot by extracting the kernel and initramfs out of the hard drive image you just created:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ . extract.sh&lt;br /&gt;
$ extract_boot_images hdimg alpine-riscv64.qcow2&lt;br /&gt;
$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel boot/vmlinux-lts \&lt;br /&gt;
    -initrd boot/initramfs-lts \&lt;br /&gt;
    -append &amp;quot;root{{=}}/dev/vda3 modules{{=}}sd-mod,usb-storage,ext4 quiet rootfstype{{=}}ext4&amp;quot;&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -noreboot}}&lt;br /&gt;
&lt;br /&gt;
The main difference here is in the image extraction (done using the hard drive image rather than the installation media) and in the &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; line, which specifies the virtio disk &amp;lt;code&amp;gt;/dev/vda3&amp;lt;/code&amp;gt; as the &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Normally the &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; parameter would be a UUID. If you prefer to use a UUID, you can grab it using a command like:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# blkid /dev/vda3}}&lt;br /&gt;
&lt;br /&gt;
And update your &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; parameter accordingly, e.g.:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|    -append &amp;quot;root{{=}}UUID{{=}}2341d7cd-e050-427e-afff-94fa0db4c8c5 modules{{=}}sd-mod,usb-storage,ext4 quiet rootfstype{{=}}ext4&amp;quot; \}}&lt;br /&gt;
&lt;br /&gt;
=== Using apk to create an image ===&lt;br /&gt;
&lt;br /&gt;
Yet another way to create a hard drive image for Alpine on RISC-V&amp;amp;nbsp;64 would be with the help of an existing Alpine system (any architecture, not just riscv64). Here are two articles that discuss this method:&lt;br /&gt;
&lt;br /&gt;
* [https://arvanta.net/alpine/install-alpine-riscv64-qemu/ install Alpine Linux riscv64 under qemu]&lt;br /&gt;
* [https://arvanta.net/alpine/install-alpine-riscv64-qemu-uboot/ install Alpine Linux riscv64 under qemu with u-boot loader]&lt;br /&gt;
&lt;br /&gt;
{{Note|These articles were created for a previous version of Alpine, and there may be differences in the way that a current &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt; deploys a new system &#039;&#039;vs&#039;&#039; the result from these scripts. However, the techniques used are still sound and may be of interest.}}&lt;br /&gt;
&lt;br /&gt;
== Contribute ==&lt;br /&gt;
* Test out the port and [https://gitlab.alpinelinux.org/alpine/aports/-/issues/?label_name%5B%5D=arch%3Ariscv64 report] the bugs you find.&lt;br /&gt;
* Write and improve guides about the port.&lt;br /&gt;
* Fix [https://gitlab.alpinelinux.org/alpine/aports packages] that are buggy or don&#039;t work on RISC-V.&lt;br /&gt;
&#039;&#039;This section is based on [https://irclogs.alpinelinux.org/%23alpine-riscv64-2025-10.log this] [[Alpine Linux:IRC|IRC]] conversation from 2025-10-01.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Riscv64]]&lt;/div&gt;</summary>
		<author><name>Fission</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Riscv64&amp;diff=32174</id>
		<title>Riscv64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Riscv64&amp;diff=32174"/>
		<updated>2026-03-25T09:56:17Z</updated>

		<summary type="html">&lt;p&gt;Fission: Added the results of my testing of the new ISO images, plus some testing of U-Boot, EDK2, and direct booting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
&lt;br /&gt;
RISC-V 64 is one of the [[architecture|architectures]] that Alpine Linux supports. The first stable release was Alpine Linux 3.20. Standard ISO images are available since Alpine Linux 3.23. You can download it from the [https://alpinelinux.org/downloads/ Alpine Linux downloads] page.&lt;br /&gt;
&lt;br /&gt;
== QEMU ==&lt;br /&gt;
&lt;br /&gt;
=== Installing QEMU for RISC-V 64 on Alpine ===&lt;br /&gt;
&lt;br /&gt;
Installing QEMU on Alpine is very straightforward:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# apk add qemu-system-riscv64 qemu-img}}&lt;br /&gt;
&lt;br /&gt;
You will need {{Pkg|qemu-img|arch=riscv64}} if you want to create QCOW2 disk images; if you only want to create raw images, it’s not needed.&lt;br /&gt;
&lt;br /&gt;
For example, to create a new 2&amp;amp;nbsp;GB QCOW2 disk image:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-img create -f qcow2 alpine-riscv64.qcow2 2G}}&lt;br /&gt;
&lt;br /&gt;
Adjust the &#039;&#039;size&#039;&#039; parameter as you see fit.&lt;br /&gt;
&lt;br /&gt;
=== Getting U-Boot ===&lt;br /&gt;
&lt;br /&gt;
[https://u-boot.org/ U-Boot], aka &#039;&#039;Das U-Boot: The Universal Boot Loader&#039;&#039;, is one of the easiest, most flexible ways to boot Alpine on RISC-V&amp;amp;nbsp;64. It can be used with GRUB for EFI booting, or with &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt; for non-EFI booting.&lt;br /&gt;
&lt;br /&gt;
You need the file &#039;&#039;&#039;&amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt;&#039;&#039;&#039; to boot using U-Boot. Alpine provides a compiled &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; in two places:&lt;br /&gt;
&lt;br /&gt;
# The &#039;&#039;&#039;Generic U-Boot tarball&#039;&#039;&#039; on the [https://alpinelinux.org/downloads/ Alpine downloads page]. Currently that is:&lt;br /&gt;
#:https://dl-cdn.alpinelinux.org/alpine/v3.23/releases/riscv64/alpine-uboot-3.23.3-riscv64.tar.gz&lt;br /&gt;
# The &#039;&#039;&#039;[https://pkgs.alpinelinux.org/package/edge/main/riscv64/u-boot-qemu &amp;lt;code&amp;gt;u-boot-qemu&amp;lt;/code&amp;gt; package for &amp;lt;code&amp;gt;riscv64&amp;lt;/code&amp;gt;]&#039;&#039;&#039;. Note that if you are not already on an Alpine riscv64 system, you won’t be able to just &amp;lt;code&amp;gt;apk add&amp;lt;/code&amp;gt; this package, as it will be for a different architecture. In practical terms this means downloading the &amp;lt;code&amp;gt;.apk&amp;lt;/code&amp;gt; file directly from an APK mirror, e.g.:&lt;br /&gt;
#:https://dl-cdn.alpinelinux.org/edge/main/riscv64/u-boot-qemu-2026.01-r0.apk&lt;br /&gt;
&lt;br /&gt;
If you downloaded the &amp;lt;code&amp;gt;.tgz&amp;lt;/code&amp;gt; file, this command will extract the &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; file to the current directory:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ tar --strip-components 3 -xf alpine-uboot-3.23.3-riscv64.tar.gz \&lt;br /&gt;
    ./u-boot/qemu-riscv64_smode/u-boot.bin}}&lt;br /&gt;
&lt;br /&gt;
If you downloaded the &amp;lt;code&amp;gt;.apk&amp;lt;/code&amp;gt; file, this command will extract the &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; file to the current directory:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ tar --strip-components 4 -xf u-boot-qemu-2026.01-r0.apk \&lt;br /&gt;
    usr/share/u-boot/qemu-riscv64_smode/u-boot.bin}}&lt;br /&gt;
&lt;br /&gt;
{{Note|There are two &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; files, but you need the one in the &amp;lt;code&amp;gt;qemu-riscv64_smode&amp;lt;/code&amp;gt; directory. That is because OpenSBI (the first thing QEMU executes) will run in &#039;&#039;M-mode&#039;&#039; (the highest privilege), which expects to execute U-Boot in &#039;&#039;S-mode&#039;&#039; (one privilege level lower).}}&lt;br /&gt;
&lt;br /&gt;
{{Warning|A [https://lists.denx.de/pipermail/u-boot/2025-August/596500.html regression exists in U-Boot 2025.10], which is included with the Alpine 3.23 release, that may prevent booting via &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt;. The error will be similar to:&lt;br /&gt;
&lt;br /&gt;
    Failed to reserve memory for fdt at 0xbee9e220&lt;br /&gt;
    FDT creation failed! hanging...### ERROR ### Please RESET the board ###&lt;br /&gt;
&lt;br /&gt;
This has been [https://github.com/u-boot/u-boot/commit/62f1afbe7a8ae8f8b9e85c5ea4eb446b97892a7c resolved in U-Boot 2026.01].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Solution:&#039;&#039;&#039; use the &amp;lt;code&amp;gt;u-boot.bin&amp;lt;/code&amp;gt; file from Alpine Edge (URL given above) APK file that has version 2026.01 or later.}}&lt;br /&gt;
&lt;br /&gt;
=== U-Boot + GRUB EFI ===&lt;br /&gt;
&lt;br /&gt;
The easiest way to run Alpine riscv64 in EFI mode is to boot from the ISO. You can download it from the [https://alpinelinux.org/downloads/ Alpine downloads page]. Here is an example of launching QEMU using U-Boot to boot this ISO:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel u-boot.bin \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}cd0}}&lt;br /&gt;
&lt;br /&gt;
The boot path is therefore:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; U-Boot =&amp;gt; GRUB EFI =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* &amp;lt;code&amp;gt;-kernel u-boot.bin&amp;lt;/code&amp;gt; is what causes OpenSBI to load U-Boot.&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* The ISO is being treated as a &amp;lt;code&amp;gt;virtio-blk-device&amp;lt;/code&amp;gt; rather than a real CD-ROM drive.&lt;br /&gt;
* After you’ve run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt;, you can remove the last two lines on subsequent launches so the ISO is no longer attached.&lt;br /&gt;
&lt;br /&gt;
It’s equally possible to boot using just the Generic U-Boot tarball. First, it needs to be fully extracted, &#039;&#039;except&#039;&#039; &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt;, which U-Boot will try to use first if present:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ mkdir alpine-uboot-3.23.3-riscv64&lt;br /&gt;
$ tar -C alpine-uboot-3.23.3-riscv64 --exclude ./extlinux/extlinux.conf \&lt;br /&gt;
    -xf alpine-uboot-3.23.3-riscv64.tar.gz}}&lt;br /&gt;
&lt;br /&gt;
Then you can launch QEMU and have it emulate the &amp;lt;code&amp;gt;alpine-uboot-3.23.3-riscv64&amp;lt;/code&amp;gt; as a [https://www.qemu.org/docs/master/system/images.html#virtual-fat-disk-images Virtual FAT disk image]:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel u-boot.bin \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd1}}&lt;br /&gt;
&lt;br /&gt;
This is nearly identical to the previous command, except the change from the ISO to the extracted tarball directory (&amp;lt;code&amp;gt;alpine-uboot-3.23.3-riscv64&amp;lt;/code&amp;gt;). Note the &amp;lt;code&amp;gt;fat:ro:&amp;lt;/code&amp;gt; syntax to emulate a virtual hard drive from a directory on the host.&lt;br /&gt;
&lt;br /&gt;
=== U-Boot + extlinux.conf ===&lt;br /&gt;
&lt;br /&gt;
U-Boot can use &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt; to boot, which does not require EFI (and therefore does not use GRUB).&lt;br /&gt;
&lt;br /&gt;
The simplest way to boot without EFI is to use the Generic U-Boot tarball. In this case, it’s extracted without modification and booted as a [https://www.qemu.org/docs/master/system/images.html#virtual-fat-disk-images Virtual FAT disk image].&lt;br /&gt;
&lt;br /&gt;
First, extract the Generic U-Boot tarball:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ mkdir alpine-uboot-3.23.3-riscv64&lt;br /&gt;
$ tar -C alpine-uboot-3.23.3-riscv64 -xf alpine-uboot-3.23.3-riscv64.tar.gz}}&lt;br /&gt;
&lt;br /&gt;
Then, launch QEMU:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel u-boot.bin \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}fat:ro:alpine-uboot-3.23.3-riscv64,if{{=}}none,id{{=}}hd1,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd1}}&lt;br /&gt;
&lt;br /&gt;
The boot path is therefore:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; U-Boot + extlinux.conf =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* &amp;lt;code&amp;gt;-kernel u-boot.bin&amp;lt;/code&amp;gt; is what causes OpenSBI to load U-Boot.&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* After you’ve run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt;, you can remove the last two lines on subsequent launches, so the virtual FAT disk image is no longer attached.&lt;br /&gt;
&lt;br /&gt;
{{Tip|You may see a usage message that begins like:&lt;br /&gt;
&lt;br /&gt;
    usage: /usr/sbin/update-u-boot [-b{{|}}--board &amp;lt;board-type&amp;gt;] [-d{{|}}--device &amp;lt;device&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
This is harmless. If it concerns you, it can be suppressed during the install by using the &amp;lt;code&amp;gt;BOOTLOADER&amp;lt;/code&amp;gt; environment variable:&lt;br /&gt;
&lt;br /&gt;
    {{Cmd|# BOOTLOADER{{=}}none setup-alpine}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
(While it is technically possible to install from the ISO using &amp;lt;code&amp;gt;extlinux.conf&amp;lt;/code&amp;gt;, doing so is more trouble than it’s worth, as you have to create a separate boot volume containing &amp;lt;code&amp;gt;/boot/vmlinuz-lts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;/boot/initramfs-lts&amp;lt;/code&amp;gt; from the ISO, and &amp;lt;code&amp;gt;/extlinux/extlinux.conf&amp;lt;/code&amp;gt; from the Generic U-Boot tarball.)&lt;br /&gt;
&lt;br /&gt;
=== EDK2 + GRUB EFI ===&lt;br /&gt;
&lt;br /&gt;
Using EDK2 is convenient in that it comes bundled with {{Pkg|qemu-system-riscv64|arch=riscv64}}. However, it does require a few more QEMU options than U-Boot to work successfully.&lt;br /&gt;
&lt;br /&gt;
Here is an example using EDK2 to boot the Alpine riscv64 standard ISO:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ cp /usr/share/qemu/edk2-riscv-vars.fd .&lt;br /&gt;
$ qemu-system-riscv64 -machine virt,acpi{{=}}off -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -drive if{{=}}pflash,format{{=}}raw,unit{{=}}0,file{{=}}/usr/share/qemu/edk2-riscv-code.fd,readonly{{=}}on \&lt;br /&gt;
    -drive if{{=}}pflash,format{{=}}raw,unit{{=}}1,file{{=}}edk2-riscv-vars.fd \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}cd0}}&lt;br /&gt;
&lt;br /&gt;
{{Warning|EDK2 will not boot the kernel without &amp;lt;code&amp;gt;acpi{{=}}off&amp;lt;/code&amp;gt;. It could be that the ACPI data QEMU is providing EDK2 is not compatible or accurate, somehow.}}&lt;br /&gt;
&lt;br /&gt;
The boot path is:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; EDK2 =&amp;gt; GRUB EFI =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* The two &amp;lt;code&amp;gt;pflash&amp;lt;/code&amp;gt; lines load two files:&lt;br /&gt;
** the EDK2 &#039;&#039;code&#039;&#039; in &amp;lt;code&amp;gt;readonly&amp;lt;/code&amp;gt; mode.&lt;br /&gt;
** the EDK2 &#039;&#039;vars&#039;&#039; (EDK2’s nvram, essentially) in a writable way.&lt;br /&gt;
**:(EDK2 doesn’t load via &amp;lt;code&amp;gt;-kernel&amp;lt;/code&amp;gt;, unlike U-Boot.)&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* After you’ve run &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt;, you can remove the last two lines on subsequent launches, so the virtual FAT disk image is no longer attached.&lt;br /&gt;
&lt;br /&gt;
{{Tip|EDK2 produces &#039;&#039;voluminous&#039;&#039; output before the Linux kernel starts. This is expected, even if seemingly abnormal.}}&lt;br /&gt;
&lt;br /&gt;
=== Direct booting ===&lt;br /&gt;
&lt;br /&gt;
“Direct” booting means using QEMU to load the kernel and initramfs files into memory and having OpenSBI boot them directly, bypassing any other bootloader such as U-Boot, EDK2, GRUB, etc. This is a very fast method of booting, but there are some points to consider:&lt;br /&gt;
&lt;br /&gt;
* You will have to somehow get the kernel and initramfs onto the host system. During installation, this is straightforward enough: you can extract them out of the installation media. But for subsequent boots (ie, after &amp;lt;code&amp;gt;apk upgrade&amp;lt;/code&amp;gt; has changed the kernel or initramfs in the guest), this becomes more challenging.&lt;br /&gt;
* Reboots will not use a new kernel from within the guest (ie, one downloaded via &amp;lt;code&amp;gt;apk upgrade&amp;lt;/code&amp;gt;), but the one that was present on the host when QEMU was first launched. For this reason, it’s suggested that you use the &amp;lt;code&amp;gt;-noreboot&amp;lt;/code&amp;gt; QEMU option to prevent reboots.&lt;br /&gt;
* Because there is no bootloader to pass kernel options, you must specify &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; QEMU options instead. Fortunately these are rather standardized.&lt;br /&gt;
&lt;br /&gt;
The boot path for this method is simply:&lt;br /&gt;
&lt;br /&gt;
    QEMU =&amp;gt; OpenSBI =&amp;gt; Linux&lt;br /&gt;
&lt;br /&gt;
==== Extracting the images ====&lt;br /&gt;
&lt;br /&gt;
To make extracting the images easier, here is a shell function you can use. It uses 7-Zip, which you can install on Alpine with &amp;lt;code&amp;gt;apk add {{Pkg|7zip|arch=riscv64}}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Cat|extract.sh|extract_boot_images() {&lt;br /&gt;
    case &amp;quot;$1&amp;quot; in&lt;br /&gt;
        iso{{!}}tar)&lt;br /&gt;
            7z x -aoa &amp;quot;$2&amp;quot; boot/vmlinuz-lts boot/initramfs-lts&lt;br /&gt;
            ;;&lt;br /&gt;
        hdimg)&lt;br /&gt;
            7z x -aoa &amp;quot;$2&amp;quot; 0.img&lt;br /&gt;
            7z x -aoa 0.img -oboot vmlinuz-lts initramfs-lts&lt;br /&gt;
            rm -f 0.img&lt;br /&gt;
            ;;&lt;br /&gt;
    esac&lt;br /&gt;
    [ -f boot/vmlinuz-lts ] &amp;amp;&amp;amp; gunzip &amp;lt; boot/vmlinuz-lts &amp;gt; boot/vmlinux-lts&lt;br /&gt;
&amp;amp;#125;}}&lt;br /&gt;
&lt;br /&gt;
This function takes two arguments: the file type, &amp;lt;code&amp;gt;iso&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;hdimg&amp;lt;/code&amp;gt;, and the filename itself.&lt;br /&gt;
&lt;br /&gt;
For the Alpine ISO or Generic U-Boot tarball, the extraction is fairly straightforward. For hard drive images (either QCOW2 or raw), it will extract the first partition (which ought to be &amp;lt;code&amp;gt;/boot&amp;lt;/code&amp;gt;, ie, &amp;lt;code&amp;gt;/dev/vda1&amp;lt;/code&amp;gt;), and then extract the images from that. In both cases, it decompresses &amp;lt;code&amp;gt;vmlinuz-lts&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;vmlinux-lts&amp;lt;/code&amp;gt;, since it seems that OpenSBI wants an uncompressed kernel image.&lt;br /&gt;
&lt;br /&gt;
{{Note|If you extract the kernel and initramfs from the ISO, you should use the ISO to install; and similarly, if you extract them from the Generic U-Boot tarball, you should use the tarball to install.}}&lt;br /&gt;
&lt;br /&gt;
==== Install booting ====&lt;br /&gt;
&lt;br /&gt;
Here is an example QEMU command line for installation booting (first using the shell script above to extract the images):&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ . extract.sh&lt;br /&gt;
$ extract_boot_images iso alpine-standard-3.23.3-riscv64.iso&lt;br /&gt;
$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel boot/vmlinux-lts \&lt;br /&gt;
    -initrd boot/initramfs-lts \&lt;br /&gt;
    -append &amp;quot;modules{{=}}loop,squashfs,sd-mod,usb-storage quiet&amp;quot; \&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -drive file{{=}}alpine-standard-3.23.3-riscv64.iso,media{{=}}cdrom,if{{=}}none,id{{=}}cd0,readonly{{=}}on \&lt;br /&gt;
    -device virtio-scsi-device,id{{=}}scsi0 \&lt;br /&gt;
    -device scsi-cd,drive{{=}}cd0,bus{{=}}scsi0.0 \&lt;br /&gt;
    -noreboot}}&lt;br /&gt;
&lt;br /&gt;
Some explanatory notes about the command:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-nographic&amp;lt;/code&amp;gt; will select a serial console (rather than a graphical one).&lt;br /&gt;
* The &amp;lt;code&amp;gt;-kernel&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;-initrd&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; lines set up the kernel boot from files on the host. The &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; string is set up for booting from install media (the ISO or tarball).&lt;br /&gt;
* The &amp;lt;code&amp;gt;-netdev&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-device virtio-net-device&amp;lt;/code&amp;gt; lines set up &#039;&#039;user-mode networking&#039;&#039; with SSH port forwarding from the host:2222 to the guest:22.&lt;br /&gt;
* &amp;lt;code&amp;gt;-noreboot&amp;lt;/code&amp;gt; prevents the system from rebooting back into the installer. (You should change the command post installation so that subsequent launches boot from your hard drive image.)&lt;br /&gt;
&lt;br /&gt;
Run the install as normal. It may attempt to install a bootloader, but it won’t be used.&lt;br /&gt;
&lt;br /&gt;
==== Normal booting ====&lt;br /&gt;
&lt;br /&gt;
After the installation, you can run a normal boot by extracting the kernel and initramfs out of the hard drive image you just created:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|$ . extract.sh&lt;br /&gt;
$ extract_boot_images hdimg alpine-riscv64.qcow2&lt;br /&gt;
$ qemu-system-riscv64 -machine virt -smp cores{{=}}2 -m 2G \&lt;br /&gt;
    -nographic \&lt;br /&gt;
    -kernel boot/vmlinux-lts \&lt;br /&gt;
    -initrd boot/initramfs-lts \&lt;br /&gt;
    -append &amp;quot;root{{=}}/dev/vda3 modules{{=}}sd-mod,usb-storage,ext4 quiet rootfstype{{=}}ext4&amp;quot;&lt;br /&gt;
    -device virtio-rng-device \&lt;br /&gt;
    -netdev user,hostfwd{{=}}tcp:127.0.0.1:2222-:22,id{{=}}n0 \&lt;br /&gt;
    -device virtio-net-device,netdev{{=}}n0 \&lt;br /&gt;
    -drive file{{=}}alpine-riscv64.qcow2,if{{=}}none,id{{=}}hd0 \&lt;br /&gt;
    -device virtio-blk-device,drive{{=}}hd0 \&lt;br /&gt;
    -noreboot}}&lt;br /&gt;
&lt;br /&gt;
The main difference here is in the image extraction (done using the hard drive image rather than the installation media) and in the &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; line, which specifies the virtio disk &amp;lt;code&amp;gt;/dev/vda3&amp;lt;/code&amp;gt; as the &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Normally the &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; parameter would be a UUID. If you prefer to use a UUID, you can grab it using a command like:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|# blkid /dev/vda3}}&lt;br /&gt;
&lt;br /&gt;
And update your &amp;lt;code&amp;gt;-append&amp;lt;/code&amp;gt; parameter accordingly, e.g.:&lt;br /&gt;
&lt;br /&gt;
{{Cmd|    -append &amp;quot;root{{=}}UUID{{=}}2341d7cd-e050-427e-afff-94fa0db4c8c5 modules{{=}}sd-mod,usb-storage,ext4 quiet rootfstype{{=}}ext4&amp;quot; \}}&lt;br /&gt;
&lt;br /&gt;
=== Using apk to create an image ===&lt;br /&gt;
&lt;br /&gt;
Yet another way to create a hard drive image for Alpine on RISC-V&amp;amp;nbsp;64 would be with the help of an existing Alpine system (any architecture, not just riscv64). Here are two articles that discuss this method:&lt;br /&gt;
&lt;br /&gt;
* [https://arvanta.net/alpine/install-alpine-riscv64-qemu/ install Alpine Linux riscv64 under qemu]&lt;br /&gt;
* [https://arvanta.net/alpine/install-alpine-riscv64-qemu-uboot/ install Alpine Linux riscv64 under qemu with u-boot loader]&lt;br /&gt;
&lt;br /&gt;
{{Note|These articles were created for a previous version of Alpine, and there may be differences in the way that a current &amp;lt;code&amp;gt;setup-alpine&amp;lt;/code&amp;gt; deploys a new system &#039;&#039;vs&#039;&#039; the result from these scripts. However, the techniques used are still sound and may be of interest.}}&lt;br /&gt;
&lt;br /&gt;
== Contribute ==&lt;br /&gt;
* Test out the port and [https://gitlab.alpinelinux.org/alpine/aports/-/issues/?label_name%5B%5D=arch%3Ariscv64 report] the bugs you find.&lt;br /&gt;
* Write and improve guides about the port.&lt;br /&gt;
* Fix [https://gitlab.alpinelinux.org/alpine/aports packages] that are buggy or don&#039;t work on RISC-V.&lt;br /&gt;
&#039;&#039;This section is based on [https://irclogs.alpinelinux.org/%23alpine-riscv64-2025-10.log this] [[Alpine Linux:IRC|IRC]] conversation from 2025-10-01.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Riscv64]]&lt;/div&gt;</summary>
		<author><name>Fission</name></author>
	</entry>
</feed>