Zombie Zen

Ross's Blog

Chromebook Hacking: Developer Mode

Posted at by Ross Light

This is the second part in my series about creating a low-cost programming environment with an HP Chromebook 11. See Part 1 of Chromebook Hacking for the overview. This blog post assumes you have some basic knowledge of using a Linux terminal.

Enable Developer Mode

Danger: This will wipe out your entire local storage! Back up everything!

Enabling developer mode on a Chromebook is the blessed way of “rooting” your Chromebook: it gives you root shell access. This comes with the cost of losing parts of ChromeOS that depend on hardware-backed security systems (namely Netflix. Sad days).

Enabling developer mode is reversible (see below), but going in either direction will wipe your Chromebook’s SSD. Please back up your files first.

Instructions are on the Chromium OS website. For the HP Chromebook 11, the short version is: hold Esc+Refresh+Power button and when you see the boot screen, tap Ctrl+D. Follow the prompts and wait for roughly 10 minutes for the operating system to reinstall.

On the boot screen, you need to press Ctrl+D every time you boot to skip the “Danger, you don’t have verified boot” screen, or you can wait for 30 seconds. You can alternatively press the spacebar to perform a factory reset and disable developer mode.

Go through the standard Chrome OS “create an account” process to get to the desktop.

Install Secure Shell and set up Crosh

This step isn’t strictly necessary, but it gives you a very slick terminal interface. If you decide not to do this, you can always open crosh with Ctrl+Alt+T.

Install Secure Shell from the Chrome Web Store. Right-click on the app’s icon in the shelf and choose “Open as Window”. This allows you to use shortcuts like Ctrl+W inside the terminal without Chrome intercepting them. Click the shelf icon to open a new terminal. Create a new profile with a random non-empty user name (I picked foo) and a host of >crosh.

Secure Shell app with user "foo" and host "crosh"

Harden your install

Open a bash shell by running shell at the crosh prompt. Inside your bash shell, run this command:

chromeos-setdevpasswd

This sets your Chromebook’s UNIX password for the chronos user — the UNIX user used for any logged in Chrome profile. Now that you’ve enabled developer mode, chronos has the ability to run sudo. Since all Chrome profiles use the same UNIX user account, you will want to open chrome://settings/accounts and whitelist the users that can access this machine. Disable Guest browsing and restrict sign-in to yourself.

Chrome settings with guest browsing disabled and sign-in restricted to Ross's account

Finally, you should prevent your Chromebook from booting anything other than ChromeOS by running the following from your bash prompt:

crossystem dev_boot_usb=0 dev_boot_signed_only=1

The first parameter (dev_boot_usb) disables booting from an external USB stick. The second parameter (dev_boot_signed_only) forbids booting to operating systems that are not signed by Google.

Wrapping Up

Now you have a minimal Linux environment with bash and vim. After poking around a bit, you will quickly notice that only Downloads and /usr/local are writable. In the next blog post, I will introduce Crouton: a less restrictive Linux environment for ChromeOS.

Chromebook Hacking

Posted at by Ross Light
HP Chromebook 11 showing a command prompt

In my spare time, I’ve been working on Go-SDL2 and Camlistore. I’m usually not sitting in front of my home desktop, so I want to be able to code anywhere. My battle-worn MacBook Pro could do the job, but it’s heavy, bulky, and aging.

To fix this, I bought the HP Chromebook 11. The display is nice, the price is great, and the keyboard is comfortable. It accepts a microUSB charge, so I don’t even have to worry about packing an extra charger. The bummer is development: good luck trying to run anything besides JSFiddle.

For a while, I was using SSH into my desktop to code. Most of the time this works. The problem was me: some days I would forget to turn on my desktop, other days I left it in Windows, and every day I gritted my teeth if I was coding graphics. I fantasized about a machine that booted quickly and had all the programs I needed.

Turns out, the answer was right in front of me: the Chromebook.

Recipe for Success!

  • Buy the Chromebook
  • Enable developer mode
  • Install Secure Shell and set up with Crosh
  • Harden your install
  • Download and run Crouton
  • Install X11 and xmonad
  • Profit!

Total Cost: $279 + half a day’s worth of work.

Over the next few days, I’ll go into more detail on these steps.

A night of fun hacks

Posted at by Ross Light

I discovered that some of my code was still living on my old laptop from high school. The laptop hadn’t been booted in about 4 years, so the clock battery had died, causing the filesystem checks to fail (this is Ubuntu 9.10, which cared about these things). I reset the clock manually, boot up the machine, and decide that to be on the safe (but marginally inefficient) side, I’ll copy my entire multi-GB home directory to my more beefy desktop and filter out what I don’t want there.

Sadly, this laptop came before 802.11n and is limited to 54 Mbps. I have an AirPort Express with only one local port, which is connected to my desktop, but I don’t want to disrupt the network setup. I realize I can chain the Ethernet from my old laptop (named metroid) to my new laptop (named roran), which has 802.11n to connect to my desktop (named nasuada).

It's a UNIX system. I know this.
ross@nasuada$ nc -l 8080 > mybackup.tar.bz2
ross@roran$ nc -l 8080 | nc nasuada.local 8080
ross@metroid$ tar -jcf - $HOME | nc roran.local 8080



I love Unix.

Why Go Does Not Need Generics

Posted at by Ross Light

(This developed from a thread with some other Cal Poly students discussing Go.)

One of the frequently asked questions about Go is why are there no generics in the language. It’s a fair point from the perspective of other OOP languages, but idiomatic Go code un-asks the question.

First, it is important to understand how interfaces work in Go. The gist is that interfaces use virtual method lookups, but retain the underlying type, so a conversion back to the original type is still type-safe. An empty interface (interface{}) works as a type-safe equivalent of C’s void*: you can put any type inside of an empty-interface variable, and then you can un-box it later.

The simplest way to define a linked list is through the empty interface: interface{}.

type Node struct {
    Value interface{}
    Next *Node
}

And indeed, this is how the container/list package package works, give or take some complexity. However, my argument is that this is the wrong way to do this. It requires an explicit boxing/un-boxing hit for every access, and this is where (I think) most of the call for generics comes from. There’s a much more idiomatic way to do this. My two case studies here are the sort package and the container/heap package from the standard library.

We start with sort, which defines an interface, sort.Interface:

package sort

func Sort(data Interface)

type Interface interface {
    // Len is the number of elements in the collection.
    Len() int
    // Less returns whether the element with index i should sort
    // before the element with index j.
    Less(i, j int) bool
    // Swap swaps the elements with indexes i and j.
    Swap(i, j int)
}

This may not strike you as a generic container, but that is precisely the point. You can – with a bit of boilerplate – create a type that wraps a typed slice that implements sort.Interface. Thus, the algorithm can work on any type and only works uses indices. This is much cheaper than boxing/unboxing on access.

The second example is container/heap:

package heap

func Init(h Interface)
func Pop(h Interface) interface{}
func Push(h Interface, x interface{})
func Remove(h Interface, i int) interface{}

type Interface interface {
    sort.Interface
    Push(x interface{}) // add x as element Len()
    Pop() interface{}   // remove and return element Len() - 1.
}

Admittedly, there is a bit more boxing/un-boxing going on here, but the idea is still similar. We now have a data structure that requires very few box/unbox operations (two per push/pop). It is important to note that this is still type-safe.

You could implement a binary tree structure similarly:

package tree

func Search(root *Node, val interface{}) *Node

type Node struct {
    Index       int
    Left, Right *Node
}

type Interface interface {
    Len() int
    Less(i, j int) bool
    Push(x interface{})
    Pop() interface{}
}

The Search function would push the val interface and use it for comparisons against the values stored in the tree, then pop it once finished. Admittedly, this isn’t the prettiest interface, but it works in a pinch. It works out to be only one box/un-box round-trip.

As we’ve seen, by “flipping” around the algorithms and separating them from the data structures using interfaces, we can still reap the benefits of generic containers from other languages.

I’m finishing up my game, “Urge to Merge”, for my Intro to Computer Graphics course. This is the first time I’ve worked with OpenGL shaders; I’m pleased with the results. These are screenshots from the game.

Something about the simplicity of the characters made me laugh even by the fourth panel.