From ee1bb0fe4d5e457480ff4ab46fd1f9cf40a1cfb2 Mon Sep 17 00:00:00 2001
From: Robert Pengelly <robertapengelly@hotmail.com>
Date: Fri, 14 Jun 2024 08:20:00 +0100
Subject: [PATCH] Create a IA16 minix compatible executable

---
 aout.c | 59 ++++++++++++++++++++++++++++++++++++++++++----------------
 aout.h | 25 ++++++++++++++++++++++++-
 ld.c   |  2 +-
 ld.h   |  6 ++++--
 lib.c  |  7 +++++++
 5 files changed, 79 insertions(+), 20 deletions(-)

diff --git a/aout.c b/aout.c
index b3200a7..a1effc9 100644
--- a/aout.c
+++ b/aout.c
@@ -27,8 +27,6 @@ typedef     signed int                  int32_t;
 static unsigned long header_size = 0, output_size = 0;
 static void *data = 0, *output = 0, *text = 0;
 
-static struct aout_exec *aout_hdr;
-
 
 struct gr {
 
@@ -199,7 +197,7 @@ static void apply_slides (struct aout_object *object) {
 
 static void paste (struct aout_object *object) {
 
-    struct aout_exec *header = object->header;
+    struct i386_aout_exec *header = object->header;
     
     char *obj_text, *obj_data;
     unsigned long obj_text_size, obj_data_size, obj_bss_size;
@@ -376,7 +374,7 @@ static int relocate (struct aout_object *object, struct relocation_info *r, int
             r_symbolnum = GET_UINT32 (r->r_symbolnum) & (3L << 29);
             r_address = GET_INT32 (r->r_address);
             
-            if (state->format == LD_FORMAT_I386_AOUT || ((r_symbolnum >> 28) & 0xff) != N_ABS) {
+            if (state->format == LD_FORMAT_IA16_AOUT || state->format == LD_FORMAT_I386_AOUT || ((r_symbolnum >> 28) & 0xff) != N_ABS) {
             
                 if (state->format == LD_FORMAT_BIN || state->format == LD_FORMAT_COM) {
                 
@@ -482,7 +480,11 @@ static int glue (struct aout_object *object) {
 
 static int init_aout_object (void) {
 
-    header_size = sizeof (*aout_hdr);
+    if (state->format == LD_FORMAT_I386_AOUT) {
+        header_size = sizeof (struct i386_aout_exec);
+    } else if (state->format == LD_FORMAT_IA16_AOUT) {
+        header_size = sizeof (struct ia16_aout_exec);
+    }
     
     if (!state->impure) {
         header_size = ALIGN_UP (header_size, SECTION_ALIGNMENT);
@@ -495,7 +497,6 @@ static int init_aout_object (void) {
     }
     
     memset (output, 0, output_size);
-    aout_hdr = output;
     
     text = (void *) ((char *) output + header_size);
     data = (void *) ((char *) text + state->text_size);
@@ -506,13 +507,39 @@ static int init_aout_object (void) {
 
 static int write_aout_object (unsigned long a_entry) {
 
-    write741_to_byte_array (aout_hdr->a_info, state->impure ? OMAGIC : ZMAGIC);
-    write741_to_byte_array (aout_hdr->a_text, state->text_size);
-    write741_to_byte_array (aout_hdr->a_data, state->data_size);
-    write741_to_byte_array (aout_hdr->a_bss, state->bss_size);
-    write741_to_byte_array (aout_hdr->a_entry, a_entry);
-    write741_to_byte_array (aout_hdr->a_trsize, tgr.relocations_count * sizeof (struct relocation_info));
-    write741_to_byte_array (aout_hdr->a_drsize, dgr.relocations_count * sizeof (struct relocation_info));
+    if (state->format == LD_FORMAT_I386_AOUT) {
+    
+        struct i386_aout_exec *aout_hdr = output;
+        
+        write741_to_byte_array (aout_hdr->a_info, state->impure ? OMAGIC : ZMAGIC);
+        write741_to_byte_array (aout_hdr->a_text, state->text_size);
+        write741_to_byte_array (aout_hdr->a_data, state->data_size);
+        write741_to_byte_array (aout_hdr->a_bss, state->bss_size);
+        write741_to_byte_array (aout_hdr->a_entry, a_entry);
+        write741_to_byte_array (aout_hdr->a_trsize, tgr.relocations_count * sizeof (struct relocation_info));
+        write741_to_byte_array (aout_hdr->a_drsize, dgr.relocations_count * sizeof (struct relocation_info));
+    
+    } else if (state->format == LD_FORMAT_IA16_AOUT) {
+    
+        struct ia16_aout_exec *aout_hdr = output;
+        
+        aout_hdr->a_magic[0] = 0x01;
+        aout_hdr->a_magic[1] = 0x03;
+        
+        aout_hdr->a_flags = 0x10;
+        aout_hdr->a_cpu = 0x04;
+        aout_hdr->a_hdrlen = sizeof (*aout_hdr);
+        
+        write741_to_byte_array (aout_hdr->a_text, state->text_size);
+        write741_to_byte_array (aout_hdr->a_data, state->data_size);
+        write741_to_byte_array (aout_hdr->a_bss, state->bss_size);
+        write741_to_byte_array (aout_hdr->a_entry, a_entry);
+        write721_to_byte_array (aout_hdr->a_total, (state->text_size + state->data_size) + 0x8000);
+        
+        write741_to_byte_array (aout_hdr->a_trsize, tgr.relocations_count * sizeof (struct relocation_info));
+        write741_to_byte_array (aout_hdr->a_drsize, dgr.relocations_count * sizeof (struct relocation_info)); 
+    
+    }
     
     if (fwrite ((char *) output, output_size, 1, state->ofp) != 1) {
     
@@ -569,7 +596,7 @@ int create_executable_from_aout_objects (void) {
         text = (void *) (char *) output;
         data = (void *) ((char *) text + state->text_size);
     
-    } else if (state->format == LD_FORMAT_I386_AOUT) {
+    } else if (state->format == LD_FORMAT_IA16_AOUT || state->format == LD_FORMAT_I386_AOUT) {
     
         if (init_aout_object ()) {
         
@@ -608,7 +635,7 @@ int create_executable_from_aout_objects (void) {
         return EXIT_FAILURE;
     }
     
-    if (state->format == LD_FORMAT_I386_AOUT) {
+    if (state->format == LD_FORMAT_IA16_AOUT || state->format == LD_FORMAT_I386_AOUT) {
         entry = get_entry ();
     }
     
@@ -654,7 +681,7 @@ int create_executable_from_aout_objects (void) {
         
         }
     
-    } else if (state->format == LD_FORMAT_I386_AOUT) {
+    } else if (state->format == LD_FORMAT_IA16_AOUT || state->format == LD_FORMAT_I386_AOUT) {
     
         if (write_aout_object (entry)) {
         
diff --git a/aout.h b/aout.h
index e30be07..87d9e4e 100644
--- a/aout.h
+++ b/aout.h
@@ -4,7 +4,30 @@
 #ifndef     _AOUT_H
 #define     _AOUT_H
 
-struct aout_exec {
+struct ia16_aout_exec {
+
+    unsigned char a_magic[2];
+    unsigned char a_flags;
+    unsigned char a_cpu;
+    unsigned char a_hdrlen;
+    unsigned char a_unused;
+    unsigned char a_version[2];
+    
+    unsigned char a_text[4];
+    unsigned char a_data[4];
+    unsigned char a_bss[4];
+    unsigned char a_entry[4];
+    unsigned char a_total[4];
+    unsigned char a_syms[4];
+    
+    unsigned char a_trsize[4];
+    unsigned char a_drsize[4];
+    unsigned char a_trbase[4];
+    unsigned char a_drbase[4];
+
+};
+
+struct i386_aout_exec {
 
     unsigned char a_info[4];
     unsigned char a_text[4];
diff --git a/ld.c b/ld.c
index f9612a5..cf640e8 100644
--- a/ld.c
+++ b/ld.c
@@ -70,7 +70,7 @@ static struct vector vec_undef = { 0 };
 
 static int process_aout (void *obj, unsigned long sz, const char *fname, int quiet) {
 
-    struct aout_exec *hdr = obj;
+    struct i386_aout_exec *hdr = obj;
     
     struct aout_object *data_obj;
     struct nlist *symtab;
diff --git a/ld.h b/ld.h
index 5c1f393..32ce20c 100644
--- a/ld.h
+++ b/ld.h
@@ -13,7 +13,7 @@ struct aout_object {
     
     unsigned long size;
     
-    struct aout_exec *header;
+    struct i386_aout_exec *header;
     struct relocation_info *trelocs, *drelocs;
     
     struct nlist *symtab;
@@ -50,7 +50,9 @@ struct ld_state {
 
 #define     LD_FORMAT_COM               0x00
 #define     LD_FORMAT_BIN               0x01
-#define     LD_FORMAT_I386_AOUT         0x02
+
+#define     LD_FORMAT_IA16_AOUT         0x02
+#define     LD_FORMAT_I386_AOUT         0x04
 
 extern struct ld_state *state;
 extern const char *program_name;
diff --git a/lib.c b/lib.c
index 6a1111a..7861b2e 100644
--- a/lib.c
+++ b/lib.c
@@ -254,6 +254,13 @@ void parse_args (int argc, char **argv, int optind) {
                 
                 }
                 
+                if (xstrcasecmp (optarg, "a.out-ia16") == 0) {
+                
+                    state->format = LD_FORMAT_IA16_AOUT;
+                    break;
+                
+                }
+                
                 if (xstrcasecmp (optarg, "a.out-i386") == 0) {
                 
                     state->format = LD_FORMAT_I386_AOUT;
-- 
2.34.1