Aiden Isik's Site - Blog


Porting AsteroidOS to the Galaxy Watch FE - Part 1

16th Dec 2025

Introduction

For the past few months (on and off), I have been working on porting AsteroidOS to my Samsung Galaxy Watch FE, a WearOS-based Samsung smart watch. AsteroidOS is a libre/open-source GNU/Linux distribution for smart watches, primarily those based on WearOS, which is a proprietary derivative of Android. This post describes how I retrieved the data I need from the watch, to help me later with the actual porting work, and as a backup in case it is ever needed.

Rooting

Samsung does not provide complete firmware images for their wearable devices, unlike their phones. This is an issue, because these files are required to restore back to WearOS if needed. They are also helpful to understand the partition layout and might help me with setting up AsteroidOS itself later. The first idea I had to get a copy of the firmware was to read data from Odin mode, however after further research it seems like that is impossible, and that Odin mode only enables writing to the flash, not reading. My second idea, and the one I went with to solve this issue, was to root the watch, connect to it over ADB, and transfer copies of each named partition, along with a whole disk image, over to my PC.

However, rooting the watch would involve modifying the stock boot.img, and since Samsung does not provide firmware images for the watch, I would not get the stock one back and so the watch would never be stock again (since I don't have Samsung's private key, which I would need to use to sign the boot.img). In an attempt to avoid this, I downloaded an over-the-air update for the watch using this project, hoping that it would contain a complete boot.img for me to save. Unfortunately it did not, it only contained a delta patch for boot.img, not the whole thing. (In hindsight I might have been able to root via the recovery partition, which I did get a full image from the OTA update for, but you live and you learn.)

I pushed on anyways. First things first, I unlocked the bootloader. That part isn't very interesting. Then, I disassembled the watch - which was really quite easy, four screws and the back just pops off, thanks Samsung! - and soldered a USB cable to the USB test points exposed on the back of the mainboard, in order to gain the ability to flash the watch via Heimdall (I did not use NetOdin due to it being leaked proprietary software). I then attempted to write a generic boot.img provided by KernelSU (a kernel-assisted rooting solution for Android) to the watch via Heimdall, however this was not successful. Heimdall was just throwing an error.

The watch with the USB cable hooked up

As it turns out, this generic boot image is too large. The image was 64MiB whereas the size of the boot partition on this watch is 48MiB. I was fortunately able to solve this issue relatively easily and shrink the image by unpacking it, then repacking it using mkbootimg with the following command:

python3 mkbootimg.py --kernel kernel --pagesize 2048 --os_patch_level 2025-03 --header_version 4 --output boot.img

With that particular issue solved KernelSU should now be installed, so I booted up the watch and attempted to connect to it over ADB. Confusingly, I got no indication while the watch was booted that it was actually connected over USB, despite me having just used it to flash the boot partition. After scouring the internet for some time, I came across an image on the XDA Developers Forum detailing what the extra USB test point (which was unlabelled on the prior diagram I saw) was for, and how to use it.

The full USB pinout for the watch, note the ID pin

It's an ID pin, and depending on the resistance to ground, it changes the behaviour of the USB points. As detailed in the image, I connected approximately (VERY approximately, in reality it's way out and I'm shocked it worked) 150k Ohms of resistance between ground and that pin, using SMD resistors I salvaged from a dead Xbox 360. I then booted up the watch, checked the output of lsusb and ADB on my PC, and it showed up! Apparently my PC thinks it is a Galaxy A5 (probably for a similar reason any device in Odin mode registers as a Galaxy SIII), but it works so I won't complain.

The fixed USB wiring

As a nice side effect, my PC was also now able to charge the watch over USB. Unfortunately I did knock a spring-loaded contact off of the board which connects to one of the antennas (try to spot where). I'll fix that later. Now that I had a connection to the watch, I tried to sideload the KernelSU app over ADB. Unfortunately, instead of installing it errored out complaining about something along the lines of an architecture mismatch.

Apparently, this watch has a 64-bit build of the Linux kernel, but userspace is 32-bit! Mainline KernelSU does not support this particular configuration. This does not make very much sense to me (why not just 64 bit?), but I had my answer as to why it wasn't working. After some hours of searching, I found a fork of KernelSU which supports this particular setup, patched it into the Android common kernel, packed that into a boot.img, and flashed it. I also installed the corresponding app onto the watch (successfully, this time).

After starting the app, it showed KernelSU to be working! So I enabled system app viewing in the superuser tab, found the shell, and granted it root access. This gives me root privileges over ADB, which will enable me to copy the contents of the flash and the Hardware Abstraction Layers (HALs).

I don't think the KernelSU app was made for watches...

Cloning the Flash

The next step was locating all of the named partitions to clone. For once, this was pretty easy, all I had to do was connect via ADB and get a directory listing of /dev/block/by-name.

Time to get what I came here for

And I had a list of partitions to dump! So with the help of a somewhat convoluted setup which involves piping the output of dd through netcat and initiating the transfer at just the right time on both the watch and the computer, I retrieved each partition, one after the other (sidenote: this was a serious pain to do and I'm sure there is a better way - I had to be very quick to run the netcat command on my PC after initiating the transfer or it wouldn't work - maybe it could be automated with some Bash scripting). I also grabbed a copy of the full flash as well, for good measure.

Imagine this, but for every single partition

Extracting the HALs

The last things I needed to get from the watch were the Hardware Abstraction Layers (HALs). Specifically, I need the proprietary Samsung vendor HALs as they are required to drive some of the watch's hardware. Technically to boot the watch these aren't required since the SoC drivers will be either kernel modules or part of the kernel, but they are required for almost everything else, including the display. At some point I will maybe look into replacing them with free/open-source drivers but for now I need them.

Extracting these was really quite simple, I just copied the entirety of the /vendor/lib and /system/lib directories to /storage/emulated/0, where I could then copy the files over to my computer via MTP, much like transferring pictures from an Android phone. Of course, I copied more than just the vendor HALs by doing this, but they can be sorted through later.

Next Steps

Now that I have everything (I think) I need from WearOS, I can get to work on the process of getting AsteroidOS itself building and running for the watch. Watch out for future blog posts on that topic.