My thoughts and ideas.

How I lock my bike and why it doesn't matter


Thanks to the YouTube algorithm, I recently got into lockpicking. YouTube is full of channels like Lockpicking Lawyer and Bosnian Bill that teach how to open locks without the keys.

After binge watching probably hundreds of videos, I decided that it was time for me to give it a shot and pick some locks, so I ordered some picks and got to picking.

I started with regular pin tumbler locks like this one:

Read more ⟶

A subtractive review of the Framework laptop


In audio, there’s this thing called subtractive synthesis, where you take a signal and subtract parts of it until you come up with a sick Acid Techno bass sound. Or some other sound, whatever. I’m going to review my Framework Laptop in the same way. In this analogy, the initial signal is going to be “a perfect laptop for me”, and I’m going to subtract things from that until the final sound is “the Framework laptop as perceived by me”.

Read more ⟶

Bypassing Go visibility rules (with generics!)


(You can paste all snippets into the Go playground.)

Bypassing the visibility rules has always been easy for structs, and there are several approaches that I will explain in this post.

The first approach involves finding the offset of the field in the struct using reflection, then the unsafe package to create an arbitrary pointer to the field.

-- go.mod --
module tmp

go 1.18


-- unsafe/some_package/some_package.go --
package some_package

type S struct {
	Number int32
	Letter rune
	secret string
}

func NewS() S {
	return S{secret: "secret string"}
}


-- main.go --
package main

import (
	"fmt"
	"reflect"
	"unsafe"

	"tmp/unsafe/some_package"
)

func main() {
	s := some_package.NewS()

	// Find the "secret" field.
	f, ok := reflect.TypeOf(s).FieldByName("secret")
	if !ok {
		panic("could not find field")
	}

	// Get the address of the struct.
	ptr := unsafe.Pointer(&s)

	// Add the offset of the field within the struct to
	// the address of the struct, effectively getting the
	// address of the field.
	ptr = unsafe.Add(ptr, f.Offset)

	// ptr now points to the address of "secret" in the
	// struct, so it can be cast to *string and then
	// dereferenced.
	strp := (*string)(ptr)
	fmt.Println(*strp)

	// Or just:
	fmt.Println(*(*string)(unsafe.Add(unsafe.Pointer(&s), f.Offset)))

	// Or just use reflect.Value, which is basically the same:
	fmt.Println(*(*string)(unsafe.Pointer(
		reflect.
			ValueOf(&s).
			Elem().
			FieldByName("secret").
			Addr().
			Pointer())))
}

This approach is fairly safe as the reflect package should be able to provide the exact offset of the field, and usage of the unsafe package is extremely easy to audit and reason about. It’s just wrong, you know. Like, philosophically.

Read more ⟶

Reverse engineering UEFI firmware to lift evil hardware restrictions


I recently got a Lenovo ThinkCentre Tiny M93. It’s a cute little device that came with pension documents for several people and is doing great as a cheap NAS. However, the main reason I got it was to replace a Raspberry Pi that I was using as a WiFi access point running Pi-Hole, and the M93 didn’t have a WiFi card when I bought it. Easy enough, I thought, just get a decent Intel mini PCI Express card and some antennas.

Read more ⟶

Drill Your Hard Drives


… after filling it with random data. And don’t sell them on eBay.

IN PARTICULAR, don’t be irresponsible enough to do this when you work for IT in something like a pension fund or a law firm.

What am I talking about then? Well, I wanted one of those cute, tiny, barebones, terminal business PC’s to replace a Raspberry Pi at home. I found a Lenovo ThinkCentre Tiny M93 on eBay, with a pretty nice 4th Gen Core i3 and 8GB of DDR3. This is enough, and was pretty damn cheap for what it is.

Read more ⟶

Using Zig and STM32 CubeMX to drive soviet VFD tubes to display the time


clock

I really like Zig. And I think it’s an awesome language to use for embedded stuff, from the way allocation is handled, to its awesome comptime feature, the build system, the “just-work"iness of it, etc. It’s also backed by LLVM and therefore is able to target the useful architectures that one should care about.

So I decided to rewrite the code for my IV-8 VFD clock, a libopencm3 STM32G0 C project in Zig to see how much nicer it would be.

Read more ⟶

How to use STM32 CubeMX without losing your mind


CubeMX is kinda nice, but it also sucks donkey ass… But it’s kinda nice! But it really sucks absolute donkey ass!

It’s kinda nice because it lets you configure your stuff easily with a GUI and then generates some questionable code that actually configures your stuff (most of the time). It sucks donkey ass because of the way they chose to do the code generation thing. You’re reading this so I’m guessing you know. I know. It’s really dumb. Literally any other approach would have most likely sucked less.

Read more ⟶