Now Reading
Operating SunOS 4 in QEMU (SPARC)

Operating SunOS 4 in QEMU (SPARC)

2023-04-12 20:11:16

SunOS is a historic UNIX working system broadly used from the mid 80s into the early/mid 90s. Older variations of QEMU struggled to emulate the SPARC platform that SunOS ran on, however QEMU v7.2 helps SPARC nicely sufficient to put in and run SunOS with none uncommon workarounds.

Set up media

The set up CD-ROM for SunOS 4.1.4 (additionally branded Solaris 1.1.2) is accessible on the Web Archive:

You may also desire a dump of the SparcStation 5 boot PROM. QEMU’s bundled OpenBIOS is able to booting SunOS, however the unique PROM is helpful for individuals who desire a extra genuine emulation expertise.

shasum -a 256 *
# 559c8455918029ffdaaf9890caf9f791c3a3604d2f2158793751b770593c0a3c  SunOS-v4.1.4.iso
# e7f40845504c65f4011278aa3e97a9810aa36775e6c199b715839fbc25eec45e  ss5.bin

Getting ready the SunOS mini-root

The primary stage of the SunOS set up course of is to arrange a minimal bootable surroundings.

SunOS is designed to run on Solar’s {hardware}, so it is comparatively fussy about machine format and configuration in comparison with an OS meant for client {hardware}. The SPARCstation 5 Service Manual is a helpful reference.

  • The inner HDD will need to have SCSI goal 3, and the interior CD-ROM will need to have SCSI goal 6.
  • SunOS expects the CD-ROM to have a bodily block dimension of 512 bytes[1].
  • Though an actual SPARCstation 5 helps as much as 256 MiB of RAM, we’ll be giving it solely 64 MiB to simplify the set up course of[2]

Go away off the -bios ss5.bin line to make use of QEMU’s built-in OpenBIOS.

qemu-system-sparc -version
# QEMU emulator model 7.2.1
# Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Mission builders
qemu-img create -f qcow2 sunos-hdd.img 2G
# Formatting 'sunos-hdd.img', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib dimension=2147483648 lazy_refcounts=off refcount_bits=16
#    -machine SS-5 
#    -m 64 
#    -bios ss5.bin 
#    -drive file=sunos-hdd.img,bus=0,unit=3,media=disk 
#    -device scsi-cd,channel=0,scsi-id=6,id=cdrom,drive=cdrom,physical_block_size=512 
#    -drive if=none,file=SunOS-v4.1.4.iso,media=cdrom,id=cdrom

As soon as on the firmware immediate, kind boot cdrom (or boot cdrom:d for OpenBIOS).

Within the disk formatter, choose disk kind 13 (SUN2.1G), write the label to disk, then stop the formatting utility.

The set up script will prep the disk for the primary installer, then immediate for a reboot.

If utilizing OpenBIOS, the VM won’t boot into mini-root by itself. Sort boot disk0:b -sw on the firmware immediate to proceed.

Putting in SunOS itself

After rebooting, you must see some logspam and a root immediate. Run suninstall to proceed the set up course of.

There is no sophisticated selections to make right here, so I simply went with the short set up of the total system.

After the set up is completed the VM will reboot and you will be again on the firmware immediate. Sort boot disk (or boot disk3:a for OpenBIOS) as well.

In its unique surroundings, a brand new SunOS workstation would have acquired its community configuration from RARP (the predecessor of DHCP) and NIS (type of a proto-LDAP). Since we do not have a lab of 100 workstations to provision, handbook information entry is ok.

The default IP deal with for QEMU’s usermode networking is, for which SunOS will assign a netmask of 0xFF000000[3].

A password ought to be six to eight characters lengthy ????.

Nearly finished. The final step is to configure the gateway router, after which the VM can have working networking. Simply log in as root, set the gateway deal with, and write it to /and many others/defaultrouter so it’s going to persist throughout reboots.

Log in as a non-root person to launch the native graphical UI of SunOS, OpenWindows.

Putting in an online browser (Netscape)

The ultimate model of SunOS was launched when the Internet was in its infancy, and due to this fact doesn’t have a bundled internet browser (or any type of HTTP-related utilities). Fortunately for us SunOS/SPARC was a well-liked platform and Netscape printed binaries for it. Truly discovering these binaries was a little bit of a slog, however I finally positioned a replica of Netscape Communicator v4.61 on the delightfully retro web page The Solbourne Solace @ Floodgap Retrobits (archive).

Within the least stunning twist ever, the tarball itself is simply out there by way of Gopher, at gopher:// I’ve mirrored it to at Netscape Communicator 4.61 [SunOS 4.1.3].

In any case, as soon as you have obtained a replica of the Netscape set up package deal you will discover that it wants gzip, which on the time was a GNU-specific expertise. I like to recommend following the handbook set up directions from README.set up in your host machine to provide a plain tarball.

shasum -a 256 communicator-v461-us.sparc-sun-sunos4.1.3_U1.tar.gz
# c667feb3a73721872d60ffd4aab24e39be8d5a48761397b4dd2184b4dd2bb5de  communicator-v461-us.sparc-sun-sunos4.1.3_U1.tar.gz
tar -xf communicator-v461-us.sparc-sun-sunos4.1.3_U1.tar.gz
cd communicator-v461.sparc-sun-sunos4.1.3_U1/
mkdir -p netscape-v4.61/java/courses
mv *.nif netscape-v4.61/
mv *.jar netscape-v4.61/java/courses/
cd netscape-v4.61/
gzip -dc netscape-v461.nif | tar -xf -
gzip -dc nethelp-v461.nif | tar -xf -
gzip -dc spellchk-v461.nif | tar -xf -
cd ..
tar -cf ../netscape-v4.61.tar netscape-v4.61/

Getting that tarball into the VM can also be a bit difficult because of the lack of widespread community protocols between 1994 and 2023. I ended up writing a helper (recv.c) that can hook up with a TCP socket and stream any information it receives to a file.

# # host
nc -Nl 5000 < netscape-v4.61.tar

# # VM
cc -o recv recv.c
./recv netscape-v4.61.tar

Unpack that tarball, write a wrapper script and a stub /and many others/resolv.conf, and Netscape is able to go.

cat /and many others/resolv.conf
# area sunos.native
# nameserver
cat ~/
# #!/bin/sh
# XNLSPATH="${HOME}/netscape-v4.61/nls"
# XKEYSYMDB="${HOME}/netscape-v4.61/XKeysymDB"
# exec "${HOME}/netscape-v4.61/netscape_dns" "$@"

Appendix A: recv.c

This ought to be pretty readable regardless of being written in Okay&R C; the BSD sockets API hasn’t modified a lot.

See Also

If you happen to do not wish to kind the entire thing in by hand, see the following part about X11 forwarding.

#embrace <arpa/inet.h>
#embrace <fcntl.h>
#embrace <netdb.h>
#embrace <netinet/in.h>
#embrace <stdio.h>
#embrace <stdlib.h>
#embrace <string.h>
#embrace <sys/socket.h>
#embrace <sys/sorts.h>
#embrace <unistd.h>

int split_server_address(server_address, server_ip, server_port)
	char *server_address;
	unsigned lengthy *server_ip;
	unsigned brief *server_port;
	char *port_str, *port_extra;
	lengthy port_raw;

	port_str = strchr(server_address, ':');
	if (port_str == NULL) {
		return -1;
	*(port_str++) = 0;

	*server_ip = inet_addr(server_address);
	if (*server_ip == -1) {
		return -1;

	port_raw = strtol(port_str, &port_extra, 10);
	if (port_raw < 1 || port_raw > 65535) {
		return -1;
	if (*port_extra != 0) {
		return -1;
	*server_port = port_raw;

	return 0;

int recv_file(server_ip, server_port, output_path)
	unsigned lengthy server_ip;
	unsigned brief server_port;
	char *output_path;
	int socket_fd, output_fd;
	struct sockaddr_in server;
	char buffer[2048];

	socket_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (socket_fd == -1) {
		return -1;

	memset(&server, 0, sizeof server);
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = server_ip;
	server.sin_port = htons(server_port);

	if (join(socket_fd, (struct sockaddr*)&server, sizeof server) == -1) {
		return -1;

	output_fd = open(output_path, O_WRONLY | O_CREAT, 0600);
	if (output_fd == -1) {
		return -1;

	whereas (1) {
		int n = learn(socket_fd, buffer, sizeof buffer);
		if (n == -1) {
			return -1;
		if (n == 0) {
			return shut(output_fd);
		write(output_fd, buffer, n);

int important(argc, argv)
	int argc;
	char **argv;
	unsigned lengthy server_ip;
	unsigned brief server_port;

	if (argc < 3) {
		fprintf(stderr, "Utilization: %s <server_address> <output_path>n", argv[0]);
		return 1;

	if (split_server_address(argv[1], &server_ip, &server_port) == -1) {
		fprintf(stderr, "Invalid server deal with "%s"n", argv[1]);
		return 1;

	if (recv_file(server_ip, server_port, argv[2]) == -1) {
		perror("Error receiving file");
		return 1;

	return 0;

Appendix B: X11 forwarding

The expertise of interacting with a GUI from 1994 by way of QEMU’s console isn’t nice, so I like to recommend working an X11 server in your host and having the VM hook up with it.

If you happen to’re already working an X11-based desktop (BSD, older Linux, macOS with XQuartz[4]) then you may proxy its socket on to TCP after which hook up with it from the VM. It will allow you to copy-paste massive blobs of textual content resembling recv.c.

# # host
socat TCP-LISTEN:6001,fork,bind= UNIX-CONNECT:/tmp/.X11-unix/X0

# # VM
setenv DISPLAY

Alternatively, use a nested X11 server resembling Xnest or Xephyr. You can run the OpenWindows window supervisor, so it feels a bit like utilizing VNC.

# # host
Xephyr -ac -listen tcp -screen 2048x1536 :1

# # VM
setenv DISPLAY

If olwm segfaults on startup, ensure that the host machine has the legacy X11 fonts put in. In Ubuntu 22.04 I needed to set up the xfonts-100dpi package deal.

  1. These days the bodily block dimension for CD-ROMs is 2048 bytes, however within the 90s this worth wasn’t standardized but. Shopper CD-ROM drives had a bodily jumper on the again that would choose the block dimension, and a few OSes (together with SunOS) would encounter learn errors if the jumper wasn’t set to what they anticipated.

  2. SunOS requires a swap partition that’s not less than as giant as machine reminiscence, and the default swap partition dimension for SUN2.1G is 100 MiB. Utilizing 64 MiB lets us keep away from fidgeting with the disk geometry within the formatting instrument.

  3. SunOS pre-dates CIDR, so it thinks of all 10.x.x.x addresses as belonging to the ten.0.0.0/8 “Class A” community. That is technically flawed for QEMU, which by default makes use of a netmask of 0xFFFFFF00, nevertheless it does not actually matter so long as you do not attempt to do something too sophisticated with multi-VM networking.

  4. Notice that the default socket path for XQuartz could comprise a colon, which is able to make socat sad as a result of it makes use of colons as a part of its choice syntax. You’ll be able to work round this with a symlink.

Source Link

What's Your Reaction?
In Love
Not Sure
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top