18
Nov
22

Installing Debian 12 with IPv6 on Oracle Cloud ARM instance for free

As you might know, Oracle Cloud still has a fairly generous offer1 with up to 4 Ampere (ARM64) cores, 24 GB RAM, 200 GB storage, an IPv4 address and 10TB of traffic, entirely free of charge.

Unfortunately there is no pre-packaged Debian image available, IPv6 isn’t enabled by default and the OpenStack management console is fairly unintuitive, so here’s a write-up on how to do it.

Step 1 – register a free account on Oracle Cloud

Visit cloud.oracle.com and register an account. It requires a credit card in your name for security purposes.

Step 2 – get the Debian image

Download an ARM64 generic cloud qcow2 Debian image from https://cloud.debian.org/images/cloud/ to your PC

For example, this one: debian-12-genericcloud-amd64-20240102-1614.qcow2

Step 3 – import the image into OCI

Go to Storage – Buckets, click Create Bucket
(select your Compartment on the left if visiting for the first time)
Click Create Bucket

Go to Storage – Buckets – your bucket, click Upload, upload your Debian image (debian-*.qcow2)
Click Upload

Go to Instances – Custom Images, click Import Image
Name: enter image file name as the image name (e.g. debian-12-genericcloud-amd64-20240102-1614)
Bucket: select your bucket
Object name: select your image
Image type: select QCOW2
Click Import Image
(this takes a while to complete)

Go to Instances – Custom Images – your image, click Edit details
Unselect everything, select VM.Standard.A1.Flex
Click Save Changes

Go to Instances – Custom Images – your image, click Edit image capabilities
Firmware: Unselect BIOS
In-transit encryption: Disabled
Click Save Changes

Step 4 – create an IPv6-enabled network

Go to Networking – Virtual Cloud Networks, click Create VCN
Name: vcn1
IPv4 CIDR Blocks: type: 10.0.0.0/24, press Enter
IPv6 Prefixes: select Assign an Oracle allocated IPv6 /56 prefix
Click Create

Go to Networking – Virtual Cloud Networks – vcn1 – Subnets – click Create Subnet
Name: subnet1
IPv4 CIDR Block: 10.0.0.0/24
IPv6 Prefixes: select Assign an Oracle allocated IPv6 /64 prefix
Oracle allocated IPv6 address: enter 00
Route Table: Default Route Table
Select Public Subnet
Dhcp Options: Default DHCP Options
Security List: Default Security List
Click Create

Go to Networking – Virtual Cloud Networks – vcn1 – Internet Gateways – click Create Internet Gateway
Name: gw1
Click Create

Go to Networking – Virtual Cloud Networks – vcn1 – Route Table – Default Route Table,
Click Add Route Rules
Select IPv4
Target Type: Internet Gateway
Destination CIDR Block: 0.0.0.0/0
Target Internet Gateway: gw1
Click Add

Again click Add Route Rules
Select IPv6
Target Type: Internet Gateway
Destination CIDR Block: ::/0
Target Internet Gateway: gw1
Click Add

Go to Networking – Virtual Cloud Networks – vcn1 – Security Lists – Default Security List
Click Ingress Rules
Ensure ingress rules for port 22 exist for both 0.0.0.0/0 and ::/0

Click Egress Rules
Ensure egress rules exist for both 0.0.0.0/0 and ::/0. If ::/0 is missing, add it.

Note: if you ever need to delete an unused VCN, first delete all Route Tables, then it will be possible to delete the VCN.

Step 5 – create the instance

Go to Compute – Instances – click Create Instance

Image and shape – click Edit
Click Change image,
Select Image source: Custom images, select your debian image
Click Change shape,
Select Ampere – VM.Standard.A1.Flex
Select 4 CPU, 24 GB RAM (max free)

Networking – click Edit
Select existing virtual cloud network – vcn1
Select existing subnet – subnet1

Add SSH keys – select Paste public keys – paste your favorite public key(s)

Boot volume – click Specify a custom boot volume size
Enter: 200 (but note, 200 is the max free, so reduce it if you plan on running other instances, and keep in mind that minimum is 50)

Click Show advanced options – Oracle Cloud Agent – Unselect everything except Compute Instance Monitoring

Click Create

If you get an “Out of capacity” error, try selecting a different availability domain under “Placement”. Some zones have multiple domains, so it’s worth checking this. If still no luck, try a different zone (re-registering an account might be required) or just wait.

If successful, congratulations, but you’re not done yet!

Go to Compute – Instances – select your instance,
Go to Attached VNICs – click on Primary VNIC,
Click on IPv6 Addresses, Assign IPv6 Address
Select Prefix, click Assign

Step 6 – configure Debian

Now you should be able to reach your server via IPv4

ssh debian@<instance-ip>

Enable IPv6:

sudo su
echo "iface enp0s3 inet6 dhcp
>/etc/network/interfaces.d/60-inet6

Install OCI agent:

apt update
apt install snapd
snap install --classic oracle-cloud-agent
reboot

Et voilà. Enjoy!


1 In case the “always free” offer changes in the future, here’s a link to an archived copy, as was seen at the time of writing.

24
Oct
16

Installing Windows 10 on a Panasonic Toughbook CF-F9

In general, the installation of Windows 10 on a Toughbook CF-F8 or CF-F9 is unremarkable. Either an upgrade or a fresh install on an empty drive will work. Then install Windows 7 64-bit drivers in a logical order (OS INF, common components, misc driver, other drivers, then the utilities). You can use the driver download manager to download them all beforehand.

There are only a couple of issues, specifically one serious one and one minor one.

The first (serious) issue is about the Intel Dynamic Power Management (ETM) driver, which is blacklisted in Windows 10, saying something along the lines that the driver is broken in Windows 10. First of all that’s a lie – the driver is working perfectly under Windows 10, and secondly, when this driver is absent, the Toughbook is unable to wake up from sleep (the CPU resets during wake-up), and the manual fan control (low/medium/high) isn’t working. This has been an issue in older versions of Windows and is still an issue in Windows 10. Needless to say, it’s quite a problem for a laptop to be unable to sleep properly.

So how do we install a blacklisted driver? The blacklisting is done at MSI level, so we need to install it manually:

  • Uninstall the built-in Intel Dynamic Power Management and/or Thermal Control Device, including the driver (can be found in Device Manager under the System category)
  • Go to DynamicPowerPerfMgmtDriver, right-click on Drivers\Etm.inf, select Install…
  • Copy x64\EtmDevPch.sys to \Windows\System32\Drivers
  • Download and import this reg file: install-etm.reg
  • Now go to the Video driver, right-click on IIPS\lmpcd.inf, select Install…
    (see update for version 1703 below)
  • Reboot
  • Before any major OS upgrade, remove the driver by removing or renaming EtmService.exe and EtmD*.sys files on your system.

Now to the second, minor issue (although I found it quite annoying). The Panasonic touchpad/wheelpad utility (the one that handles circular scrolling) isn’t working in Windows 10 metro apps (Edge browser, Store, etc.). To fix, download and install this patch, which is basically a shim that patches the utility to call SendInput instead of posting WM_MOUSEWHEEL messages.

All done! Enjoy!

===== UPDATE June 2017 =====

Something seems to have been changed in Windows 10 version 1703 – it seems to install the ETM driver automatically and it has an updated Panasonic Hotkey driver (0019). But the ETM driver now indeed isn’t working properly – the fan control works but the driver crashes on wake-up (bugcheck 139 in EtmDrvMgr.sys). I was able to kind of make it work again by uninstalling the Intel Turbo Boost driver (lmpcd).

10
May
13

BMW MRSZ “1 internal ECU error” fix

I lost almost an entire day trying to figure out what went wrong when I was playing with my E36 airbag module coding in an attempt to disable passenger seat occupancy detection.

I didn’t understand why most MRSZ settings were duplicated, such as these two:

ERKENNUNG_SITZBELEGUNG_1
	aktiv
ERKENNUNG_SITZBELEGUNG_2
	aktiv

I set only one of these to “nicht_aktiv”, after which the module threw an “internal ECU error” and the FS_LOESCHEN command returned ERROR_ECU_REJECTED. Even after I restored all coding settings back to their original values, the error remained.

As it turns out, after digging through 24KB of microcode, the reason to duplicate every setting is very simple – it is a form of EEPROM error detection. The unit periodically checks to see if every setting has the same value in both copies, and when that is not the case, a static error 195 is logged. Every error code above 100 is mapped to the “internal ECU error”, and when that happens the erase function is also blocked.

Fortunately, at the same time I also found a “secret” command to write EEPROM bytes. Not all areas can be written with that command, but at least the area where the errors are stored is writable.

Attached is an EDIABAS script that attempts to “reanimate” an MRSZ unit. Note that you need to restore the coding to a working state before running the script. NCSExpert’s SG_CODIEREN command will end with an error, that is because it tries to erase errors at the end of the process, which fails, the actual coding should in fact be OK.

MRSZ_FIX.PRG (beta)

Note – the script supports only MRSZ units (MRS v06, P/N 8374799), it does not support MRSZ2 (MRS v07, P/N 8372521), MRSZ3 or MRSZ4. The “secret” command simply does not exist in these modules. I do not know if it supports the older ZAE2 (P/N 8374798) units.

The source code of my MRSZ2 attempt can be found here. It includes working support for MRSZ.

06
Jan
12

Groovy is COOL

Of course Groovy is much more than Java, but for Java coders like myself, it can be seen as Java without its time-eating annoyances, the absolute top 3 of which, in my opinion, are:

1. Getters and setters are implicit

2. Lists, Maps and Regex are part of the syntax

3. Configuration is greatly simplified

Item 1 is self explanatory, I hope 🙂 For the remaining two, here are some examples:

Working with collections:

def list = [5, 6, 7, 8]
for (i in list) println i
def map = [name:"Gromit", likes:"cheese", id:1234]
for (i in map) println "map[${i.key}] is ${i.value}"

Pulling Maven dependencies inline with your code, without any other configuration anywhere:

@Grab(group='mysql', module='mysql-connector-java', version='5.1.18')
driver = new com.mysql.jdbc.Driver()
Properties p = new Properties()
 p['username']='groovy-test'
 p['password']=''
conn = driver.connect('jdbc:mysql://localhost/groovy-test', p)
st = conn.createStatement()
for (i in 1..10) {
 st.executeUpdate("insert into test(name,value,version) values('name${i}','value for name${i}',0)")
}
st.close()
conn.close()

Of course Groovy is a dynamically typed language, and as such has its downsides. Since the compiler can’t type-check assignments, you get much more run-time errors like:

No signature of method: java.util.ArrayList.get() is applicable for argument types: (java.lang.String)

Or

Cannot cast object ‘x’ with class ‘java.lang.String’ to class ‘int’

Most of these errors are caught when you try out your code for the first time, though, and are easily fixable. It’s just a bit annoying at the beginning for someone used to getting these at compile time rather than at run time.

To me, Groovy is still a clear winner if you want to boost your coding productivity 🙂

Oh yeah, and the performance of Groovy is not significantly worse than that of Java (if you don’t use too many dynamic features), as I confirmed in this post.

05
Jan
12

Motorola AP-7131 dependent mode?

It seems that not all AP-7131’s are the same. There are some that are meant to be used only together with a central controller like RFS4000 or RFS6000.

This is called, in Motorola terms, ‘dependent mode’, and is hard-coded into the device. The “D” in the model ID stands for “dependent”, like in this example:

Motorola AP-7131-66000-D-WR

Such a device will not enable any radio unless directed to do so by a central controller.

One of the reasons this is done is to prevent theft of access points from public locations.

05
Jan
12

Detect MIME type of most popular Internet files

This code can detect among others PDF, Microsoft Word, Excel, Powerpoint & Visio, without even knowing the file extension.

 

sub detectMime(\$)
{
  my ($s)=@_;
  return 'text/html' if $$s =~ /^(\xEF\xBB\xBF)*\s*<(\!--|\!?doctype|html|head|body|title|h1)/is;
  return 'text/xml' if $$s =~ /^(\xEF\xBB\xBF)*\s*<\?xml/s;
  return 'application/rtf' if $$s =~ /^\{\\rtf/s;
  my @b=unpack('C520',$$s);
  return 'image/jpeg' if $b[0]==0xFF && $b[1]==0xD8;
  return 'image/gif' if $b[0]==0x47 && $b[1]==0x49 && $b[2]==0x46;
  return 'image/png' if $b[0]==0x89 && $b[1]==0x50 && $b[2]==0x4E && $b[3]==0x47;
  return 'image/bmp' if $b[0]==0x42 && $b[1]==0x4D;
  return 'image/tiff' if $b[0]==0x49 && $b[1]==0x49 && $b[2]==0x2A;
  return 'application/pdf' if $b[0]==0x25 && $b[1]==0x50 && $b[2]==0x44 && $b[3]==0x46;
  return 'image/x-icon' if $b[0]==0 && $b[1]==0 && $b[2]==1 && $b[3]==0 && $b[4]==1;
  if ($b[0]==0xD0 && $b[1]==0xCF && $b[2]==0x11 && $b[3]==0xE0 && @b>0x200) {
    return 'application/msword' if $b[0x200]==0xEC;
    return 'application/vnd.ms-excel' if $b[0x200]==0x09;
    return 'application/vnd.ms-powerpoint' if $b[0x200]==0x40;
    return 'application/vnd.visio' if $b[0x200]==0xFD;
  }
  for (my $i=@b-1;$i>=0;$i--) { return 'application/octet-stream' if $b[$i]<32 && $b[$i]!=9 && $b[$i]!=10 && $b[$i]!=13 }
  return 'text/plain';
}
05
Jan
12

SDBM hash implementation in PHP

The SDBM hashing function is a simple and fast function that provides surprizingly uniform distributions of the hash value even when applied to a series of relatively short strings (3-7 characters). This makes it an excellent algorithm for organizing multiple files in sub-directories, for example, but the possible applications are, of course, endless.

Implementing the SDBM hashing in PHP is not an easy task, however. The SDBM hash function relies on a 32-bit overflow, which doesn’t work well in PHP due to its built-in overflow handling and automatic type conversion, which is also implemented differently on different platforms.

After much trial and error, the following cute piece of code has been found to perform correctly in PHP 5.2/5.3 on 32-bit as well as 64-bit systems.

function sdbmHash($str)
{
	$hash = 0; $n=strlen($str);
	for ($i=0; $i<$n; $i++) {
		$h1 = $hash << 6;
		if ($h1<0) $h1+=0x100000000;
		$h2 = $hash << 16;
		if ($h2<0) $h2+=0x100000000;
		$h3=($hash>=0x80000000?0x100000000-$hash:-$hash);
		$hash = (int)((int)ord($str[$i]) + $h1 + $h2 + $h3);
		if($hash<0) $hash=$hash+0x100000000;
	}
	return $hash;
}
05
Jan
12

“MySQL server has gone away”

When you try to insert a BLOB that exceeds your server’s maximum packet size, even on a local server you will see “MySQL server has gone away” on the client side, and “Error 1153 Got a packet bigger than ‘max_allowed_packet’ bytes” in the server log. To fix this you need to decide what is the size of the largest BLOB you’ll ever insert, and set max_allowed_packet in my.ini accordingly, for example:

[mysqld]
 ...
 max_allowed_packet = 200M
 ...

 

05
Jan
12

PHP vs. Ruby/JRuby on Rails vs. Grails vs. Java performance comparison

In this write-up I captured my findings about the performance of various frameworks that I was considering for my next project…

Test setup:

  • One MySQL 5.1 table consisting of an ID and 2 string columns, 1000 rows (+5 for warm-up)
  • a simple web application that:
    • reads one record from the table
    • displays record data on a web page in table form
The page is accessed sequentially 5 times to warm up the caches, then 1000 times (timed). The time is captured below.

Test subjects:

  1. PHP 5.3.3 on Apache 2.2.21
  2. Ruby 1.8.7 + Rails 3.1.3 on mongrel 1.1.5
  3. JRuby 1.6.5 (emulating Ruby 1.8.7) + Rails 3.1.3 on mongrel 1.1.5
  4. Grails 2.0.0 (Groovy 1.8.4) on Tomcat 7.0.16
  5. Java 1.7 + Spring 3 on Tomcat 7.0.23

Everything was set to ‘production mode’. Test platform: win32.

Test results:

Framework Time per request
PHP 10.6ms
Ruby/Rails 14.1ms
JRuby/Rails 16.0ms
Grails/Groovy 7.4ms
Java 6.4ms

Java seems to be a clear winner here… too bad it’s by far the slowest of the 5 to develop in! :-[]

p.s. I know my JRuby setup is awkward… I just couldn’t get any sane performance out of it on a Tomcat. The perf I got in this post is the best I could achieve.

27
Sep
11

Stupid AP-7131 power socket

Hooked up a Motorola AP-7131 to a 300W 48V power supply today… incorrectly 🙂

PAF! Said Motorola.

Usually a bad sign.

As it turned out a fix is surprisingly painless: one 22uF 63V (or more) capacitor  (C403) and one 1 Ohm resistor (R400).

There is also plenty of space so you don’t need SMD components.

This is the cap that blew:

Sorry, no pic of the blown resistor. It’s hard to see anyway, looks almost normal.

And here is the new cap:

And the resistor (it is on the other side):




May 2024
M T W T F S S
 12345
6789101112
13141516171819
20212223242526
2728293031