Working custom coreboot ROM on HP Chromebook 14!

Because I am so hopelessly addicted to hacking Chromebooks, and because the ASUS Chromebook users who couldn’t boot USB got me into hacking mode, I have *finally* managed to get a working custom ROM on the HP Chromebook 14.

As noted, it breaks power-saving even more than it was already. But, on the plus side, it boots a few seconds faster, and I think it runs a bit faster too (but that could be car wash syndrome either).

Without further ado! Please see the pre-built firmware page!

ASUS Chromebox Owners Rejoice!

I have a fix for the nasty bug which stops you booting from USB in SeaBIOS on the ASUS Chromebox. It’s an updated CBFS filesystem for the RW_LEGACY slot of the firmware, which contains an updated version of SeaBIOS. Simply download the file and apply it in the Crosh shell like so (you don’t need hardware write-protect disabled)

sudo flashrom -w -i RW_LEGACY:asus-chromebox-SeaBIOS-new.bin

http://johnlewis.ie/asus-chromebox-SeaBIOS-new.bin

md5sum dc200444a02eafcce0486fedf86bf4f1

Beer me on your way out!

Another General Notice

I’ve mentioned and murmured about this from time to time, but I feel there’s no point trying to compile coreboot for newer (> Pixel) Chromebooks, as it won’t give you significant, extra functionality. Making it official here. Have unsubscribed from the coreboot mailing list. Happy to help people that want it (and ask nicely) but I’m scaling back my efforts forthwith.

General Notice

I have been forced to remove Disqus from this site, because Disqus were stupidly forwarding my moderation emails to commenters, giving people my phone numbers contained in the signature.

I’ve installed “Comments Evolved” as a drop-in replacement which supports G+ by default. Happy commenting.

Apologies for the missing information.

More Pythoning


#!/usr/bin/python -tt
# Copyright 2014 John Lewis
# This is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import sys
import re
import mysql.connector
# Iptables module.
import iptc

def build_blocked_list():
 table = iptc.Table(iptc.Table.FILTER)
 rule = iptc.Rule()
 chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'INPUT')
 blocked_ips = []
 for chain in table.chains:
 for rule in chain.rules:
 blocked_ips.append(re.sub('/255.255.255.255', '', rule.src))
 return blocked_ips

def iptables_block(ip):
 table = iptc.Table(iptc.Table.FILTER)
 rule = iptc.Rule()
 chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'INPUT')
 rule.in_interface = 'eth0'
 rule.src = ip
 t = rule.create_target('DROP')
 chain.insert_rule(rule)

def check(db, dbusername, dbpassword, logfile):
 dbconnection = mysql.connector.connect(user=dbusername, password=dbpassword,
 database=db)
 dbcursor = dbconnection.cursor()
 ipblocks_query = ('select ipb_address from ipblocks where ipb_address=%s')
 user_query = ('select user_name from user where user_name=%s')

blocked_ips = build_blocked_list()

with open(logfile, 'r') as f:
 f = f.readlines()

for line in f:
 select = re.search('(^\d\d\d\.\d\d\d\.\d\d\d\.\d\d\d).+User:(\w+)', line)
 if select:
 dbcursor.execute(ipblocks_query, (select.group(2),))
 row = dbcursor.fetchone()
 # If user in ipblocks table, block IP if not already.
 if row is not None and select.group(1) not in blocked_ips:
 blocked_ips.append(select.group(1))
 iptables_block(select.group(1))
 else:
 dbcursor.execute(user_query, (select.group(2),))
 row = dbcursor.fetchone()
 # If user *not* in user table, block IP if not already.
 if row is None and select.group(1) not in blocked_ips:
 blocked_ips.append(select.group(1))
 iptables_block(select.group(1))

def main():
 args = sys.argv[1:]
 if not args:
 print 'usage: db dbusername dbpassword logfile'
 sys.exit(1)

if len(args) < 4:
 print 'error: you must specify a db, dbusername, dbpassword, AND logfile'
 sys.exit(1)

db = args[0]
 dbusername = args[1]
 dbpassword = args[2]
 logfile = args[3]

check(db, dbusername, dbpassword, logfile)

if __name__ == '__main__':
 main()

 

How to make SeaBIOS the default on your Acer C720

Divulged this evening by Duncan Laurie on the coreboot mailing list:

If you want to boot SeaBIOS by default and you have unlocked the SPI flash write protection you can set flags in the (write protected) “GBB” flash region that will make it boot legacy mode by default.

In Chrome OS there is a script called set_gbb_flags.sh that will do this for you. Run the script with no arguments to get a list of possible flags and then to enable short dev mode screen (1 second timeout) followed by default legacy mode boot you could use these flags:

GBB_FLAG_DEV_SCREEN_SHORT_DELAY 0×00000001
GBB_FLAG_FORCE_DEV_SWITCH_ON 0×00000008
GBB_FLAG_FORCE_DEV_BOOT_LEGACY 0×00000080
GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY 0×00000400

set_gbb_flags.sh 0×489

Script Updated

I’ve modified the Python script responsible for blocking SPAMMY Mediawiki IP’s to monitor the log file in real-time. There are also a couple of other changes:

  • Added 1 second sleep to main loop to stop script eating 100% CPU, but still catch log data as it’s added.
  • Added regex substitution to remove underscore characters from username (otherwise db searches for usernames containing spaces won’t work)
  • Indented the second block of iptables code properly so it actually only blocks an IP if the user doesn’t exist.

http://pastebin.com/mztbqwuN

Mediawiki SPAMMERS die!

Here is my possibly very dodgy Python script for checking if Mediawiki usernames are banned/non-existent in an Nginx log file and then blocking the associated IP with iptables (if it’s not blocked already). Only 700,000 odd lines to process …


# Regex module.
import re
# Mysql module.
import mysql.connector
# Iptables module.
import iptc

# Nginx log-file variable.
infile = r"/var/log/nginx.log"

# Connection to Mediawiki database.
dbconnection = mysql.connector.connect(user='mysql', password='yourpassword', database='your_mediawiki_database')

# Non-interactive Mysql cmd line to pipe commands through.
dbcursor = dbconnection.cursor()

# Blocklist Mysql query.
ipblocks_query = ("select ipb_address from ipblocks where ipb_address=%s")
# User Mysql query.
user_query = ("select user_name from user where user_name=%s")

table = iptc.Table(iptc.Table.FILTER)
rule = iptc.Rule()
chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), "INPUT")

# Open log-file.
with open(infile) as f:
 f = f.readlines()

# Iterate through each line in log-file.
for line in f:
 # Select lines which contain an IP address at line start AND user talk page reference.
 if re.findall("^\d+\.\d+\.\d+\.\d+", line) and re.findall("User:\w+", line):
 found = 0
 # Replace line with IP address and user reference only.
 line = re.findall("^\d+\.\d+\.\d+.\d+|User:\w+", line)
 # Check if ip address is already blocked by iptables.

for chain in table.chains:
 for rule in chain.rules:
 if re.sub("/255.255.255.255", "", rule.src) == line[0]:
 found = 1
 break
 if found == 0:
 line[1] = re.sub("User:", "", line[1])
 line[1] = re.sub("_"," ", line[1])
 # Query user against ipblocks table.
 dbcursor.execute(ipblocks_query, (line[1],))
 print (line[1])
 row = dbcursor.fetchone()
 # If user exists in ipblocks table.
 if row is not None:
 print ("Is banned!")
 # If not found add to iptables.
 rule.in_interface = "eth0"
 rule.src = line[0]
 t = rule.create_target("DROP")
 chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), "INPUT")
 chain.insert_rule(rule)
 print ("Blocking IP address with iptables")
 print ("-")
 # Check if user exists in user table.
 else:
 dbcursor.execute(user_query, (line[1],))
 row = dbcursor.fetchone()
 if row is not None:
 print ("Is not banned!")
 print ("-")
 # If user doesn't exist block IP with iptables..
 else:
 print ("Does not exist!")
 rule.in_interface = "eth0"
 rule.src = line[0]
 t = rule.create_target("DROP")

chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), "INPUT")
 chain.insert_rule(rule)
 print ("Blocking IP address with iptables")
 print ("-")

BTW, the indentation is completely screwed there, sorry …

RHCE qualified sysadmin + coreboot on Chromebooks