x2100

I have an expression that I like to use for situations like these. Actually, as with many of my expressions, it's an expression that I like to use for near-as-I-can-tell any situation at all, but it seems extra fitting here: "I'm not sure what I expected, but I definitely got it". And so it seems to be now. You see, about ten months ago, I ordered a very bizarre, very Chinese laptop, with the intention of using it as my primary machine, and two weeks ago, at long last, it finally arrived. It's very weird, and I love it -- especially now that I've spent a week hacking on it to make it work. And I don't know how my life always seems to go this way, but for the second time in recent memory, I now find myself in a WeChat thread with the ODM of a piece of hardware that I have, making heavy use of machine translation to ask questions like "so, how much current does is this inductor rated for, anyway?".
I guess I should probably clarify what this thing is, huh? It looks like an old Thinkpad, but, really, it's... modern. A few years ago, some guys in Shenzhen decided that the Thinkpad X201 is the epitome of a Thinkpad, the One True Thinkpad, and that everything after that is garbage from a butt and not worth buying. And they decided that, since the X201 is the perfect Thinkpad, they ought to preserve the look and feel of it, but improve it (I know that feel, dudes.). So, like any rationally thinking people would do, they put the X201's mainboard in a coordinate measuring machine, and commissioned some other guys in Shenzhen to build a replacement motherboard, except with modern chips, and presto! The "X210" was born, featuring a Kaby Lake CPU. (Well, almost a Kaby Lake CPU. It's an engineering sample of a Kaby Lake CPU. But what you gonna do?)
Well, in 2019, I was on a trip to Shenzhen, and I knew I wanted one. I had a fantastic wild goose chase around Huaqiangbei -- the big electronics market -- looking for one of these things, only to find that they are way more rare than I thought. I had no success at all. When I got back home, I sent a WeChat to Jacky, who was the main guy building these machines up at the time. It turns out that they were just about to build up the "4th batch" of these machines, but there was a problem: they'd run out of engineering sample Kaby Lakes, and they were going to switch to Comet Lake, and could I wait for that to happen? Well, sure, why not? So, again, like a rationally thinking person, I happily sent a Western Union transfer for about a thousand bucks to some guy in China who didn't have the machine I was looking for, but who promised to have it, with any luck, in February or March or so.
Presumably you know the rest of the story. COVID-19 happened. Then Chinese New Year happened. Then more COVID-19 happened. Then... well, electronics just take a long time. Since it was taking so long, and there was a new chip in there, they decided to rename the project -- the first through third batches were the "X210", but this one, the special edition with even newer silicon, this one would be named the "X2100". And after months and months of waiting, and continually refreshing the 51nb forums through Google Translate, to my eternal surprise, a week or so ago, ... a machine showed up!
The thing you have to understand about this machine is that, well, it's... not exactly a consumer device. For example, the very first thing you do when you get it is to go into the BIOS, and turn down the Turbo Boost limits, because if you don't, it'll draw more power than the charger port is capable of supplying, and if you're really unlucky, it'll fry itself trying to pump 65W into the CPU. (The CPU can take it, and the cooling system -- custom-designed by the mysterious "17m19" -- can take it, but the motherboard's voltage regulators really prefer not to sustain a whole lot more than 30W.) And the power management subsystem of the machine has, uh, "charm": if you use a 9-cell battery, then as soon as you unplug it from a full charge, it'll instantly crater to 10%. Not great.
But the other thing that you have to understand about the machine is that the people who buy it are not exactly consumers. To the degree that the firmware on the ACPI embedded controller (a little microprocessor that's responsible for scanning the keyboard, dimming the backlight, reading the battery, spinning the fans, blinking the LEDs, and running the charge controller) is total dog shit on this machine, its userbase seems to have met the challenge on previous versions of the machine, running the EC firmware through Ghidra and making a pretty good collection of modifications to the it.
Anyway, when I got it, I made a list of three concerns that I hoped I could fix up. For one, there was the battery-charge-level-craters bug, from above; for two, the machine didn't seem to know how to report immediate power consumption (and therefore, couldn't estimate how much time it had left on battery); and for three, the machine charged glacially slowly (like, it'd take six or so hours to charge). I figured that I'd better get to business.
The obvious thing to start off with was to catch up with where the X210 folks left off. They had left a bunch of bread crumbs, and more than that, they had left a Ghidra database! I spent some time with their Ghidra database side by side with an empty Ghidra database for the X2100's EC. Finding the first few functions to label was something of a challenge, but once I bootstrapped the call graph a little bit, I could quickly start matching functions from their database and labeling even more of mine. I did a binary diff of Vladisslav2001's latest patched EC firmware against the original, and started looking to see what he'd changed; I isolated a few things that he'd patched, and brought those into my firmware image. With any luck, I'd have the changes that allowed me to "hot-patch" the EC: adding read-from and write-what-where primitives, without having to reflash the EC again (other than, of course, that first time to add the changes).
Reflashing the BIOS ROM on your machine with something that you've
modified is always an exciting affair. mjg59, in his blog post on extending
the X210 firmware, wrote about the perils of this: apparently if you put
something incorrect on the X210's SPI ROM, the system will become very
difficult to reflash, even if you have an external programmer (which I
don't, anyway). I was very glad to have the hot-patch changes, but getting
them on the machine for the first time was a puckering experience.
It reminded me of being a kid and making configuration changes to my machine
repeatedly (usually, when I had something better I was supposed to be
doing): "if it ain't broke, fix it until it is"! But after a few rounds, I
managed to both not brick the machine, and I had a hot-patchable EC -- which
meant that debugging the rest of the changes was going to be much easier
(and, more to the point, much less dangerous).
I spent an evening or so just getting acquainted with the way the EC was structured before I managed to make any progress on my goals. As I was writing about this, I realized that the process of reverse engineering is not exactly linear or predictable: it feels more like a stochastic process of fits and starts, and it often feels as much like luck that I stumble on the right function at any particular moment as it feels like skill. And so it was during the initial phase that I was quite fortunate to find a function that seemed to be responsible for doing ... something ... to the battery's state of charge; upon further inspection, it seemed to be taking an average of the last ten readings of the battery's charge state. This was promising!
Now, one thing you should know about the EC is that it's... well... a weird machine. It's not an 8-bit micro like an 8051, but it's also not anything modern like a Cortex-M. Instead, it's a CompactRISC CR16C, which has -- as the name might suggest -- 16-bit general-purpose registers, and, beyond that, as far as I can tell, the weirdest instruction encoding on earth (32-bit literals are encoded middle-endian!). So it might not be a surprise to find that, when this average routine adds ten readings together, that it can overflow if the battery is charged to more than 6,553 mAh! This explained a lot -- my battery is good for about 8000 mAh, and the battery starts behaving itself around 80%. I had just tripped over my first change -- I found the instruction that overwrote battery capacity with the average (why was that there, anyway?), clobbered it with NOPs, and -- thanks to Vladisslav2001's memory write support -- sent a patch over to my EC. And, moments later, without even rebooting, I had a new, accurate, battery reading!
The other two went along a similar path of slowly annotating a Ghidra database. Eventually, I had to write large chunks of assembly, and hand-assembling those just wasn't really going to fly for much longer; per Matthew's post, above, I cross-compiled a CR16 binutils, and wrote some hacky tooling to convert binutils-assembled stuff to things that the hotpatch loader (and radare2, which was responsible for patching an EC binary) could read. Along the way, while I was struggling with the fast charge changes, I found myself chatting with Xue Yao, another assembler of X2100 machines, who seemed thankful for the changes that I had already made -- and, interestingly, who had an in with the guys who built the board in the first place!
There are countless ways that this could have gone, but in reality, there was only one. Like any reasonable, rational person, I found myself in a WeChat thread with the folks who commissioned the motherboard, the folks who implemented it, and -- importantly -- a built-in WeChat Translate, because almost nobody else in the thread spoke English. It worked about as well as one might hope -- I asked for information about how the EC was implemented, they told me they couldn't provide source because it was under NDA, I asked for hints, they sent me screenshots of disassembly with the comment "look at this part" in the hopes that I would go away, I fed it into Ghidra, and everyone walked away happy, because apparently, this is how my life operates now.
Anyway, I guess, this is the story of how I wired money to China, bought the world's weirdest laptop with a half-implemented microcontroller, made a few bugfixes, and became the de-facto BIOS maintainer for it. Man, my life is weird. But who doesn't need in their life a 12" laptop with 32GB of RAM, a screaming fast processor, a 3k-by-2k display, custom code running on the EC, and ... a VGA port on the side? If there's anything that my life needs more than that, you let me know.
If you don't have a Dreamwidth account, but you want to get notified so you can read more things like this when I write them, I also have an e-mail list; I promise I'll only send mail for things that I write that go here on this blog. And, if this sort of skillset sounds like the kind of development work that you or your business needs, you can hire me through my consultancy, Accelerated Tech!