Re­cently, feel­ing re­stric­ted by the hard­ware on my laptop, I built my­self a desktop com­puter based on a re­cently re­leased Ryzen CPUs by AMD. These CPUs are built on a new ar­chi­tec­ture, plug into a new sort of socket and have a whole new eco­sys­tem around them.

Mother­board was one of the most dif­fi­cult things to de­cide on. I wanted to go for a small sys­tem, but one, that’s large enough for fu­ture ex­pan­sion into wa­ter cool­ing. This meant go­ing for a smal­ler form factor mother­board – µATX of, even bet­ter, mITX. Alas, nobody had re­leased any mother­boards of mITX form factor by the time, so µATX was the only choice.

After some re­search I de­cided on the MSI B350M MOR­TAR ARC­TIC mother­board, be­cause it had a pretty nice fea­ture set (S/P­DIF, sens­ible num­ber of USB ports, RGB head­er) and matched the col­our scheme of my white build as well!

Trouble did­n’t take long at all to rear its head. Turns out the mother­board uses a pro­pri­et­ary Su­per I/O chip: Nu­vo­ton NC­T6795D! This chip is known to be re­spons­ible for little, but im­port­ant, de­tails such as mon­it­or­ing tem­per­at­ures around the board, con­trolling the speed of fans and so on. This chip is ap­par­ently made ex­clus­ively for MSI and MSI re­fuses to provide the spec­sheets for the chip:

me: Ad­di­tion­ally, please re­lease/­give me the spec­sheet for NC­T6795D chip.

MSI: We are sorry that we can­not sup­ply the de­tails spec of it, Or you can con­tact the chip­set vendor dir­ectly.Thanks!

me: What about the RGB head­er? Nu­vo­ton is on re­cord say­ing that we should re­quest the spec­sheets from you as it is a chip de­signed spe­cific­ally for MSI. Can you please com­mu­nic­ate with Nu­vo­ton and make sure the sheets are re­leased?

MSI: We are sorry that we can­not sup­ply the de­tails spec of it. Sorry for any in­con­veni­ence caused you.

me: pretty please?

MSI: We are sorry that the de­tailed data­sheet is re­lated with con­fid­en­tial of MSI and the Man­u­fac­turer. It can­not be made pub­lic due to con­fid­en­ti­al­ity agree­ment. Sorry for the in­con­veni­ence caused you.

That’s a shame, but this ex­change was by no means a worth­less one. Even if in­dir­ectly, it points out where the RGB header is con­trolled. I de­cided to fol­low this lead.

Be­ing a stu­dent, I get to claim one of those free everything Mi­crosoft li­censes free of charge. Hav­ing in­stalled the Win­dows 10, MSI’s Gam­ing App (the pro­gram which al­lows con­trol of the RGB head­er) and a copy of RWEverything1 I start dig­ging around. Shortly after I’m greeted by great news: chan­ging the col­our in the Gam­ing App would also make the bot­tom two rows change sig­ni­fic­antly as well!

RWEverything re­act­ing to col­our changes with the Gam­ing App
RWEverything re­act­ing to col­our changes with the Gam­ing App

The next day, as I was col­lect­ing the in­form­a­tion about what each bit in the sI/O re­gisters does, I no­ticed the re­gisters not ac­tu­ally chan­ging the col­our un­less the Gam­ing App was turned on first. Wor­ried about hit­ting a dead end, I star­ted look­ing into dis­as­sem­blers and de­bug­gers on Win­dows. The ob­vi­ous first op­tion was MS­VC. Dis­ap­point­ingly, I could­n’t make to work in the end – its de­bug­ger re­fused to show me the dis­as­sembly no mat­ter what. I ended up set­tling on x64dbg, a very awe­some visual de­bug­ger­/dis­as­sem­bler.

Pick­ing at the dis­as­sembly of MSI_LED.exe even­tu­ally led me to two in­ter­est­ing func­tions: IoPortWriteByte and DeviceIoControl, which the former func­tion calls. Noth­ing, that would look like ac­tual writ­ing to an I/O Port, though. I sel­dom do any­thing with Win­dows and this is my first time look­ing into Win­dows’ in­tern­als too. That’s the reason why it took me till Sat­urday to real­ise that the ac­tual com­mu­nic­a­tion hap­pens in­side a driver of some sort, not the ex­ecut­able I was look­ing at.

Could I de­bug a driver in a live sys­tem? Turns out it is pos­sible, but not without a second com­puter with a serial head­er. Not only I haven’t an­other com­puter, I do not have a cable that could do serial either. In the end, I ended up dis­as­sembling the driver it­self, learn­ing the Win­dows driver ba­sics as I went. Know­ing noth­ing about Win­dows drivers meant stum­bling around and fig­ur­ing what all the as­sembly did. Luck­ily, the driver was only 4KiB in size, so by the even­ing I had a nice trace of the in and out in­struc­tions that the Gam­ing App in­dir­ectly in­vokes:

PORT 4E DATA 87
PORT 4E DATA 87
PORT 4E DATA 07
PORT 4F DATA 12
PORT 4E DATA F0
PORT 4F DATA 00
PORT 4E DATA 87
PORT 4E DATA 87
PORT 4E DATA 07
PORT 4F DATA 12
PORT 4E DATA F1
PORT 4F DATA 00
...

Boot back into Linux-land, open("/dev/port", "wb"), re­peat all the same calls… to my de­light – the col­our changes! Hoo­ray!

There are some out­stand­ing ques­tions, such as: “Why did­n’t, then, writ­ing straight sI/O re­gister via RWEverything work?” I don’t know. It might be the un­usual se­quence of 87 87 07 12 that ap­pears be­fore every write in the dumps2. I’m glad it all works, and am not go­ing to risk brick­ing my board a second time.

All this is im­ple­men­ted in a util­ity tool called msi-rgb. In the end this util­ity tool ended up be­ing much more flex­ible com­pared to the MSI’s own app. While msi-rgb does not mon­itor the CPU tem­per­at­ure or re­act to the mu­sic, it al­lows for much more cus­tom­isa­tion than the 7 static col­ours offered by the Win­dows app. I haven’t yet in­vest­ig­ated mak­ing the util­ity more port­able, but it should­n’t be too hard see­ing the only really un­port­able part in it is the use of /dev/port device.