Some notes to help future porters. Replace 'ARCH' with whatever arch you are hacking on. ==================== === Config Files === ==================== - create extra/Configs/Config.ARCH See the other arch files for some good examples. powerpc/sparc/alpha should be pretty simple templates. - add ARCH to the 'Target Architecture' list in extra/Configs/Config.in - Initially you will want to disable shared libraries, since making the shared library loader work requires you first have basic architecture support working. Thus you should add ARCH_HAS_NO_SHARED and ARCH_HAS_NO_LDSO to Config.ARCH's TARGET_ARCH ==================== === libc sysdeps === ==================== (note: if glibc has already been ported to your arch, you can usually just copy a lot of files from them rather than coding from scratch) - create libc/sysdeps/linux/ARCH - copy Makefile and Makefile.arch from libc/sysdeps/linux/i386/ - set CSRC and SSRC to nothing in Makefile.arch for now - create crt1.S which defines the _start function ... you will probably want to clear the frame pointer to make gdb happy, and then you will want to call the funcion __uClibc_main() which takes these parameters: __uClibc_main(main(), argc, argv, _init(), _fini()) Initially if you wish to make things easier on yourself, you can disable the UCLIBC_CTOR_DTOR option and just set the init/fini arguments to NULL. glibc generally stores this function in libc/sysdeps/ARCH/elf/start.S - create these additional files in ARCH/bits/ (template versions can be found in common/bits/ for you to tweak) endian.h fcntl.h setjmp.h stackinfo.h uClibc_arch_features.h wordsize.h kernel_types.h should be created based upon linux asm-ARCH/posix_types.h copy linux asm-ARCH/stat.h to bits/kernel_stat.h create syscalls.h based upon linux's unistd.h / glibc's sysdeps.h ... really you just want to define the _syscall[0-6] macros. It is important that these syscalls should be PIC safe (or you should provide a PIC and non-PIC version) if you wish to properly support shared libraries. - at this point, you should have enough to generate a working HELLO WORLD static binary (see test/silly/*.c files) - if you want UCLIBC_CTOR_DTOR support, you will need to create crti.S and crtn.S files which define function prologues/epilogues. - for a more stable static port, you will need to create these files (and update the Makefile.arch values accordingly) __longjmp bsd-_setjmp bsd-setjmp brk clone setjmp syscall vfork usually these are written in assembler, but you may be able to cheat and write them in C ... see other ports for more information ==================== === pthread deps === ==================== TODO: nptl / linuxthreads / linuxthreads.old ==================== === ldso sysdeps === ==================== - elf.h - presumably you've already taught binutils all about the random ELF relocations your arch needs, so now you need to make sure the defines exist for uClibc. make sure the EM_### define exists and all of the R_###_### reloc defines. - enable ldso/shared options in your extra/Configs/Config.ARCH file - you will need to create the following files in ldso/ldso/ARCH/ dl-debug.h dl-startup.h dl-syscalls.h dl-sysdep.h elfinterp.c resolve.S - dl-debug.h: define string versions of all the relocations of your arch in the _dl_reltypes_tab array ... the index should match the actual reloc type, so if the value of say R_X86_64_PC16 is 13, then "R_X86_64_PC16" better be at index 13 of the array - dl-startup.h: - define the _start function which should call _dl_start which takes just one parameter ... a pointer to argc (usually on the stack) glibc stores this function in libc/sysdeps/ARCH/dl-machine.h as RTLD_START - define the GET_ARGV() macro which calculates the value of argv based upon the parameter passed to _dl_start (usually it's simply just ARGS+1) - define PERFORM_BOOTSTRAP_RELOC() macro which will handle just the relocs that the ldso itself will generate - dl-syscalls.h: if you wrote your bits/syscalls.h file correctly in the libc step above, you can simply copy this file from another arch and be done ... otherwise you will have to define the syscall[0-6] macros again, but this time setting _dl_errno instead of just errno - dl-sysdep.h: misc cruft goes in here ... you want to: - either define or undefine ELF_USES_RELOCA - define the INIT_GOT macro - define MAGIC1 to the EM_### value your ELF arch uses - define ELF_TARGET to a string name for your arch - define the do_rem() macro - define misc ALIGN macro's - define elf_machine_type_class() macro - define the inline functions elf_machine_dynamic, elf_machine_load_address, and elf_machine_relative glibc stores a bunch of these values in libc/sysdeps/ARCH/dl-machine.h - elfinterp.c: define all the relocation functions ... it's best if you just copy from another arch which uses the same type of relocations (REL or RELA) and start from there. - resolve.S: front end of lazy relocation ... define the _dl_linux_resolve symbol which is called by a PLT entry which has yet to be setup ... you will want to: - set up arguments for _dl_linux_resolver() - call _dl_linux_resolver() - clean up after call - jump to function address now stored in PLT glibc stores this function in libc/sysdeps/ARCH/dl-trampoline.S - utils/ldd.c - if you want support for ldso cache files (spoiler: you do), then you'll need to teach ldd a little. generally, the fallback code should be smart and "just work", but you should be explicit. just pop it open and add an appropriate ifdef for your arch and set MATCH_MACHINE() and ELFCLASSM. there are plenty examples and you're (hopefully) smart. ==================== === Misc Cruft === ==================== - utils/readelf.c - not really needed generally speaking, but might as well add your arch to the giant EM_* list (describe_elf_hdr) - MAINTAINERS - presumably you're going to submit this code back to mainline and since you're the only one who cares about this arch (right now), you should add yourself to the toplevel MAINTAINERS file. do it. rg TDC 3610, QIC-24"}, \ {MT_ISARCHIVE_VP60I, "Archive VP60i, QIC-02"}, \ {MT_ISARCHIVE_2150L, "Archive Viper 2150L"}, \ {MT_ISARCHIVE_2060L, "Archive Viper 2060L"}, \ {MT_ISARCHIVESC499, "Archive SC-499 QIC-36 controller"}, \ {MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \ {MT_ISWT5099EEN24, "Wangtek 5099-een24, 60MB"}, \ {MT_ISTEAC_MT2ST, "Teac MT-2ST 155mb data cassette drive"}, \ {MT_ISEVEREX_FT40A, "Everex FT40A, QIC-40"}, \ {MT_ISSCSI1, "Generic SCSI-1 tape"}, \ {MT_ISSCSI2, "Generic SCSI-2 tape"}, \ {0, NULL} \ } /* Structure for MTIOCPOS - mag tape get position command. */ struct mtpos { long int mt_blkno; /* Current block number. */ }; #define _IOT_mtpos /* Hurd ioctl type field. */ \ _IOT_SIMPLE (long) /* Structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended as an interim solution for QIC-02 until DDI is fully implemented. */ struct mtconfiginfo { long int mt_type; /* Drive type. */ long int ifc_type; /* Interface card type. */ unsigned short int irqnr; /* IRQ number to use. */ unsigned short int dmanr; /* DMA channel to use. */ unsigned short int port; /* IO port base address. */ unsigned long int debug; /* Debugging flags. */ unsigned have_dens:1; unsigned have_bsf:1; unsigned have_fsr:1; unsigned have_bsr:1; unsigned have_eod:1; unsigned have_seek:1; unsigned have_tell:1; unsigned have_ras1:1; unsigned have_ras2:1; unsigned have_ras3:1; unsigned have_qfa:1; unsigned pad1:5; char reserved[10]; }; #define _IOT_mtconfiginfo /* Hurd ioctl type field. */ \ _IOT (_IOTS (long), 2, _IOTS (short), 3, _IOTS (long), 1) /* XXX wrong */ /* Magnetic tape I/O control commands. */ #define MTIOCTOP _IOW('m', 1, struct mtop) /* Do a mag tape op. */ #define MTIOCGET _IOR('m', 2, struct mtget) /* Get tape status. */ #define MTIOCPOS _IOR('m', 3, struct mtpos) /* Get tape position.*/ /* The next two are used by the QIC-02 driver for runtime reconfiguration. See tpqic02.h for struct mtconfiginfo. */ #define MTIOCGETCONFIG _IOR('m', 4, struct mtconfiginfo) /* Get tape config.*/ #define MTIOCSETCONFIG _IOW('m', 5, struct mtconfiginfo) /* Set tape config.*/ /* Generic Mag Tape (device independent) status macros for examining mt_gstat -- HP-UX compatible. There is room for more generic status bits here, but I don't know which of them are reserved. At least three or so should be added to make this really useful. */ #define GMT_EOF(x) ((x) & 0x80000000) #define GMT_BOT(x) ((x) & 0x40000000) #define GMT_EOT(x) ((x) & 0x20000000) #define GMT_SM(x) ((x) & 0x10000000) /* DDS setmark */ #define GMT_EOD(x) ((x) & 0x08000000) /* DDS EOD */ #define GMT_WR_PROT(x) ((x) & 0x04000000) /* #define GMT_ ? ((x) & 0x02000000) */ #define GMT_ONLINE(x) ((x) & 0x01000000) #define GMT_D_6250(x) ((x) & 0x00800000) #define GMT_D_1600(x) ((x) & 0x00400000) #define GMT_D_800(x) ((x) & 0x00200000) /* #define GMT_ ? ((x) & 0x00100000) */ /* #define GMT_ ? ((x) & 0x00080000) */ #define GMT_DR_OPEN(x) ((x) & 0x00040000) /* Door open (no tape). */ /* #define GMT_ ? ((x) & 0x00020000) */ #define GMT_IM_REP_EN(x) ((x) & 0x00010000) /* Immediate report mode.*/ /* 16 generic status bits unused. */ /* SCSI-tape specific definitions. Bitfield shifts in the status */ #define MT_ST_BLKSIZE_SHIFT 0 #define MT_ST_BLKSIZE_MASK 0xffffff #define MT_ST_DENSITY_SHIFT 24 #define MT_ST_DENSITY_MASK 0xff000000 #define MT_ST_SOFTERR_SHIFT 0 #define MT_ST_SOFTERR_MASK 0xffff /* Bitfields for the MTSETDRVBUFFER ioctl. */ #define MT_ST_OPTIONS 0xf0000000 #define MT_ST_BOOLEANS 0x10000000 #define MT_ST_SETBOOLEANS 0x30000000 #define MT_ST_CLEARBOOLEANS 0x40000000 #define MT_ST_WRITE_THRESHOLD 0x20000000 #define MT_ST_DEF_BLKSIZE 0x50000000 #define MT_ST_DEF_OPTIONS 0x60000000 #define MT_ST_BUFFER_WRITES 0x1 #define MT_ST_ASYNC_WRITES 0x2 #define MT_ST_READ_AHEAD 0x4 #define MT_ST_DEBUGGING 0x8 #define MT_ST_TWO_FM 0x10 #define MT_ST_FAST_MTEOM 0x20 #define MT_ST_AUTO_LOCK 0x40 #define MT_ST_DEF_WRITES 0x80 #define MT_ST_CAN_BSR 0x100 #define MT_ST_NO_BLKLIMS 0x200 #define MT_ST_CAN_PARTITIONS 0x400 #define MT_ST_SCSI2LOGICAL 0x800 /* The mode parameters to be controlled. Parameter chosen with bits 20-28. */ #define MT_ST_CLEAR_DEFAULT 0xfffff #define MT_ST_DEF_DENSITY (MT_ST_DEF_OPTIONS | 0x100000) #define MT_ST_DEF_COMPRESSION (MT_ST_DEF_OPTIONS | 0x200000) #define MT_ST_DEF_DRVBUFFER (MT_ST_DEF_OPTIONS | 0x300000) /* The offset for the arguments for the special HP changer load command. */ #define MT_ST_HPLOADER_OFFSET 10000 /* Specify default tape device. */ #ifndef DEFTAPE # define DEFTAPE "/dev/tape" #endif #endif /* mtio.h */