/* BootLinker.java, Copyright 1997 (c) by G. Fankhauser, Swiss Federal Institute of Technology, Computer Engineering and Networks Laboratory. TOPSY -- A Teachable Operating System. Implementation of a tiny and simple micro kernel for teaching purposes. For further information, please visit http://www.tik.ee.ethz.ch/~topsy This software is provided under the terms of the GNU General Public Licence. A full copy of the GNU GPL is provided in the file COPYING found in the development root of Topsy. */ /* File: $Source: /usr/drwho/vault/cvs/topsy/Topsy/Boot/mips/BootLinker.java,v $ Author(s): G. Fankhauser Affiliation: ETH Zuerich, TIK Version: $Revision: 1.3 $ Creation Date: January 1997 Last Date of Change: $Date: 1999/12/13 21:48:25 $ by: $Author: ruf $ $Log: BootLinker.java,v $ Revision 1.3 1999/12/13 21:48:25 ruf GNU General Public Licence Update Revision 1.2 1999/09/16 13:39:34 gfa *** empty log message *** Revision 1.1 1999/06/10 13:16:40 jeker cleaning up Revision 1.2 1999/06/09 17:04:34 gfa added byte cast to hex array for java 1.2 Revision 1.1 1997/05/09 14:28:28 gfa Initial revision # Revision 1.7 1997/04/28 18:01:27 gfa # adapted parseInt to parseLong for java 1.1 # # Revision 1.6 1997/04/13 16:22:57 gfa # added user-in-kernel-at address # # Revision 1.5 1997/03/26 16:35:00 gfa # binary output # # Revision 1.4 1997/03/26 13:58:06 gfa # we only write the segmap now... # # Revision 1.3 1997/03/22 11:55:20 conrad # added .sbss data segment # # Revision 1.2 1997/03/15 14:23:14 gfa # *** empty log message *** # # Revision 1.1 1997/02/04 11:15:26 topsy # Initial revision # */ import java.lang.*; import java.io.*; public class BootLinker extends Object { public final static String OUTFILE = "segmap.bin"; public static void main(String argv[]) throws Exception { String a, b, s = null; File f; if (argv.length != 5) { System.out.println( "usage: java BootLinker <kSizeFile> <iSizeFile> <user.srec> SEGMAPADDR USERINKERNELAT" ); System.exit(0); } try { f = new File(OUTFILE); f.delete(); } catch (Exception e) { } RandomAccessFile segmapFile = new RandomAccessFile(OUTFILE, "rw"); RandomAccessFile kSizeFile = new RandomAccessFile(argv[0], "r"); RandomAccessFile iSizeFile = new RandomAccessFile(argv[1], "r"); RandomAccessFile userSrec = new RandomAccessFile(argv[2], "r"); // write segmentMap (sizes and start addresses of kernel and // user segments). we assume that the sizeFile was generated // by gnu-size with options -Ax (addresses, hex) // ex.: size -Ax try { //// write segment map // segmapFile.writeBytes("S3" + // record type // "29" + // const length 41 bytes // argv[3]); // where it goes (segmap addr) segmapFile.seek(0); parseSizeFile(kSizeFile, segmapFile); // size/start info kernel parseSizeFile(iSizeFile, segmapFile); // size/start info init try { while (true) { s = userSrec.readLine(); if ((s.charAt(0) == 'S') && (s.charAt(1) == '7')) { //segmapFile.writeBytes(s.substring(4,12)); segmapFile.writeInt( Integer.parseInt(s.substring(4,12), 16) ); } } } catch (Exception e) { } // write the user-in-kernel-address at the end segmapFile.writeInt((int)Long.parseLong(argv[4], 16)); // if (segmapFile.getFilePointer() != 84) { // System.out.print("BootLinker: couldn't write segmap\n"); // System.exit(-1); // } // data is in, now write the checksum //segmapFile.writeBytes("00"); //segmapFile.writeBytes("\n"); } catch (Exception e) { throw e; } } static void parseSizeFile(RandomAccessFile sizeFile, RandomAccessFile out) throws IOException{ int addr = 0, size = 0; // expect text if (expect(sizeFile, ".text")) { size = readHexInt(sizeFile); addr = readHexInt(sizeFile); } // writeHexInt(out, size); writeHexInt(out, addr); out.writeInt( size); out.writeInt(addr); // expect data, add sizes up and find start address by minimizing size = 0; addr = 0; if (expect(sizeFile, ".data")) { size = readHexInt(sizeFile); addr = readHexInt(sizeFile); } if (expect(sizeFile, ".rdata")) { size += readHexInt(sizeFile); addr = Math.min(addr, readHexInt(sizeFile)); } if (expect(sizeFile, ".bss")) { size += readHexInt(sizeFile); addr = Math.min(addr, readHexInt(sizeFile)); } if (expect(sizeFile, ".sbss")) { size += readHexInt(sizeFile); addr = Math.min(addr, readHexInt(sizeFile)); } // writeHexInt(out, size); writeHexInt(out, addr); out.writeInt( size); out.writeInt(addr); } static void writeHexInt(RandomAccessFile segmapFile, int hex) throws IOException{ byte hexArray[] = {(byte)'0',(byte)'1',(byte)'2',(byte)'3',(byte)'4',(byte)'5',(byte)'6',(byte)'7', (byte)'8',(byte)'9',(byte)'A',(byte)'B',(byte)'C',(byte)'D',(byte)'E',(byte)'F'}; for (int i = 0; i < 8; i++) { segmapFile.writeByte(hexArray[(hex >> 28) & 0xf]); hex = hex << 4; } } static boolean expect(RandomAccessFile f, String exp) throws IOException { String s; long pos; f.seek(0); while (true) { try { pos = f.getFilePointer(); s = f.readLine(); if (s.length() < exp.length()) continue; if (exp.equals(s.substring(0, exp.length()))) { f.seek(pos+exp.length()); return true; } } catch (Exception e) { return false; } } } static int readHexInt(RandomAccessFile f) throws IOException { int value = 0, tmp; // skip white space byte c = f.readByte(); while ((c == ' ') || (c == '\t')) { c = f.readByte(); } // understands 0x hexprefix for newer binutils... (gfa) if (c == '0') { c = f.readByte(); if (c == 'x') { c = f.readByte(); } else { f.seek(f.getFilePointer() - 1); } } int i = 28; while (isHex(c)) { tmp = readHexByte(c); value |= ((tmp & 0xf) << i); i-=4; c = f.readByte(); } return (value >>> (i+4)); } static byte readHexByte(byte b) { char aChar = 'a'; char nullChar = '0'; if ((b >= nullChar) && (b < (nullChar+10))) { return (byte)(b - nullChar); } else if ((b >= aChar) && (b < (aChar+6))) { return (byte)(b - aChar + 10); } else { return (byte)0; } } static boolean isHex(byte c) { return ((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')); } } class BootLinkerSizeFormatException extends Exception { }