mirror of
https://github.com/kenshineto/kern.git
synced 2025-04-06 19:01:05 +00:00
remove trailing whitespace
This commit is contained in:
parent
8683b472a6
commit
6ece4e20ac
18 changed files with 42 additions and 105 deletions
1
Makefile
1
Makefile
|
@ -34,6 +34,7 @@ build:
|
|||
|
||||
fmt:
|
||||
clang-format -i $(shell find -type f -name "*.[ch]")
|
||||
sed -i 's/[ \t]*$$//' $(shell find -type f -name "*.[chS]" -or -name "*.ld")
|
||||
|
||||
bin/boot.bin: build
|
||||
cd bin && \
|
||||
|
|
14
boot/boot.S
14
boot/boot.S
|
@ -17,7 +17,7 @@
|
|||
**
|
||||
** The bootstrap initially sets up a stack in low memory. Next, it
|
||||
** loads a second sector at 0000:7E00 (immediately following the
|
||||
** boot block). Then it loads the target program at TARGET_ADDR,
|
||||
** boot block). Then it loads the target program at TARGET_ADDR,
|
||||
** switches to protected mode, and branches to the target program.
|
||||
**
|
||||
** NOTE: To zero out the BSS segment, define CLEAR_BSS when this code
|
||||
|
@ -222,11 +222,11 @@ done_loading:
|
|||
call dispMsg
|
||||
|
||||
jmp switch /* move to the next phase */
|
||||
|
||||
|
||||
/*
|
||||
** Support routine - display a message byte by byte to the monitor.
|
||||
*/
|
||||
dispMsg:
|
||||
dispMsg:
|
||||
pushw %ax
|
||||
pushw %bx
|
||||
repeat:
|
||||
|
@ -238,7 +238,7 @@ repeat:
|
|||
jz getOut /* if we've reached the NUL, get out */
|
||||
|
||||
int $BIOS_VIDEO /* otherwise, print and repeat */
|
||||
jmp repeat
|
||||
jmp repeat
|
||||
|
||||
getOut: /* we're done, so return */
|
||||
popw %bx
|
||||
|
@ -373,7 +373,7 @@ switch:
|
|||
movl %cr0, %eax /* get current CR0 */
|
||||
orl $1, %eax /* set the PE bit */
|
||||
movl %eax, %cr0 /* and store it back. */
|
||||
|
||||
|
||||
/*
|
||||
** We'll be in protected mode at the start of the user's code
|
||||
** right after this jump executes.
|
||||
|
@ -447,13 +447,13 @@ enable_A20:
|
|||
|
||||
a20wait: /* wait until bit 1 of the device register is clear */
|
||||
movl $65536, %ecx /* loop a lot if need be */
|
||||
wait_loop:
|
||||
wait_loop:
|
||||
inb $KBD_STAT, %al /* grab the byte */
|
||||
test $2, %al /* is the bit clear? */
|
||||
jz wait_exit /* yes */
|
||||
loop wait_loop /* no, so loop */
|
||||
jmp a20wait /* if still not clear, go again */
|
||||
wait_exit:
|
||||
wait_exit:
|
||||
ret
|
||||
|
||||
a20wait2: /* like a20wait, but waits until bit 0 is set. */
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
** Declarations and descriptions of console I/O routines
|
||||
**
|
||||
** These routines provide a rudimentary capability for printing to
|
||||
** the screen and reading from the keyboard.
|
||||
** the screen and reading from the keyboard.
|
||||
**
|
||||
** Screen output:
|
||||
** There are two families of functions. The first provides a window
|
||||
|
@ -50,7 +50,7 @@
|
|||
** Keyboard input:
|
||||
** Two functions are provided: getting a single character and getting
|
||||
** a newline-terminated line. A third function returns a count of
|
||||
** the number of characters available for immediate reading.
|
||||
** the number of characters available for immediate reading.
|
||||
** No conversions are provided (yet).
|
||||
*/
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
} while (0)
|
||||
|
||||
/*
|
||||
** We need the list of program IDs so that we can request
|
||||
** We need the list of program IDs so that we can request
|
||||
** their execution
|
||||
*/
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
** See IA-32 Intel Architecture SW Dev. Manual, Volume 3: System
|
||||
** Programming Guide, page 2-8.
|
||||
*/
|
||||
|
||||
/*
|
||||
** EFLAGS
|
||||
*/
|
||||
|
@ -142,7 +141,6 @@
|
|||
** 4: base address 23:16
|
||||
** 7: base address 31:24
|
||||
*/
|
||||
|
||||
/*
|
||||
** Byte 5: access control bits
|
||||
** 7: present
|
||||
|
@ -261,7 +259,6 @@
|
|||
/*
|
||||
** Interrupt vectors
|
||||
*/
|
||||
|
||||
// predefined by the architecture
|
||||
#define VEC_DIVIDE_ERROR 0x00
|
||||
#define VEC_DEBUG_EXCEPTION 0x01
|
||||
|
|
|
@ -12,13 +12,11 @@
|
|||
/*
|
||||
** BIOS-related memory addresses
|
||||
*/
|
||||
|
||||
#define BIOS_BDA 0x0400
|
||||
|
||||
/*
|
||||
** Selected BIOS interrupt numbers
|
||||
*/
|
||||
|
||||
#define BIOS_TIMER 0x08
|
||||
#define BIOS_KBD 0x09
|
||||
#define BIOS_VIDEO 0x10
|
||||
|
|
|
@ -54,7 +54,6 @@ static inline void movsb(void *dst, const void *src, uint32_t len) OPSINLINED
|
|||
:
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void movsw(void *dst, const void *src, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep movsw"
|
||||
|
@ -62,7 +61,6 @@ static inline void movsw(void *dst, const void *src, uint32_t len) OPSINLINED
|
|||
:
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void movsl(void *dst, const void *src, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep movsl"
|
||||
|
@ -70,7 +68,6 @@ static inline void movsl(void *dst, const void *src, uint32_t len) OPSINLINED
|
|||
:
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void movsq(void *dst, const void *src, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep movsq"
|
||||
|
@ -97,7 +94,6 @@ static inline void stosb(void *dst, uint8_t val, uint32_t len) OPSINLINED
|
|||
: "0"(dst), "1"(len), "a"(val)
|
||||
: "memory", "cc");
|
||||
}
|
||||
|
||||
static inline void stosw(void *dst, uint16_t val, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep stos2"
|
||||
|
@ -105,7 +101,6 @@ static inline void stosw(void *dst, uint16_t val, uint32_t len) OPSINLINED
|
|||
: "0"(dst), "1"(len), "a"(val)
|
||||
: "memory", "cc");
|
||||
}
|
||||
|
||||
static inline void stosl(void *dst, uint32_t val, uint32_t len) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("cld; rep stosl"
|
||||
|
@ -134,42 +129,36 @@ static inline uint32_t r_cr0(void) OPSINLINED
|
|||
__asm__ __volatile__("movl %%cr0,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t r_cr2(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%cr2,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t r_cr3(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%cr3,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t r_cr4(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%cr4,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t r_eflags(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("pushfl; popl %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t r_ebp(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
__asm__ __volatile__("movl %%ebp,%0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t r_esp(void) OPSINLINED
|
||||
{
|
||||
uint32_t val;
|
||||
|
@ -188,22 +177,18 @@ static inline void w_cr0(uint32_t val) OPSINLINED
|
|||
{
|
||||
__asm__ __volatile__("movl %0,%%cr0" : : "r"(val));
|
||||
}
|
||||
|
||||
static inline void w_cr2(uint32_t val) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("movl %0,%%cr2" : : "r"(val));
|
||||
}
|
||||
|
||||
static inline void w_cr3(uint32_t val) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("movl %0,%%cr3" : : "r"(val));
|
||||
}
|
||||
|
||||
static inline void w_cr4(uint32_t val) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("movl %0,%%cr4" : : "r"(val));
|
||||
}
|
||||
|
||||
static inline void w_eflags(uint32_t eflags) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("pushl %0; popfl" : : "r"(eflags));
|
||||
|
@ -222,7 +207,6 @@ static inline void w_gdt(void *addr) OPSINLINED
|
|||
{
|
||||
__asm__ __volatile__("lgdt (%0)" : : "r"(addr));
|
||||
}
|
||||
|
||||
static inline void w_idt(void *addr) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("lidt (%0)" : : "r"(addr));
|
||||
|
@ -246,7 +230,6 @@ static inline void cpuid(uint32_t op, uint32_t *ap, uint32_t *bp, uint32_t *cp,
|
|||
__asm__ __volatile__("cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(op));
|
||||
|
||||
if (ap)
|
||||
*ap = eax;
|
||||
if (bp)
|
||||
|
@ -308,14 +291,12 @@ static inline uint8_t inb(int port) OPSINLINED
|
|||
__asm__ __volatile__("inb %w1,%0" : "=a"(data) : "d"(port));
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline uint16_t inw(int port) OPSINLINED
|
||||
{
|
||||
uint16_t data;
|
||||
__asm__ __volatile__("inw %w1,%0" : "=a"(data) : "d"(port));
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline uint32_t inl(int port) OPSINLINED
|
||||
{
|
||||
uint32_t data;
|
||||
|
@ -339,12 +320,10 @@ static inline void outb(int port, uint8_t data) OPSINLINED
|
|||
{
|
||||
__asm__ __volatile__("outb %0,%w1" : : "a"(data), "d"(port));
|
||||
}
|
||||
|
||||
static inline void outw(int port, uint16_t data) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("outw %0,%w1" : : "a"(data), "d"(port));
|
||||
}
|
||||
|
||||
static inline void outl(int port, uint32_t data) OPSINLINED
|
||||
{
|
||||
__asm__ __volatile__("outl %0,%w1" : : "a"(data), "d"(port));
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
** Our expected configuration is two PICs, with the secondary connected
|
||||
** through the IRQ2 pin of the primary.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Port addresses for the command port and interrupt mask register port
|
||||
** for both the primary and secondary PICs.
|
||||
|
@ -42,7 +41,6 @@
|
|||
** PIC2_* defines are intended for the secondary PIC
|
||||
** PIC_* defines are sent to both PICs
|
||||
*/
|
||||
|
||||
/*
|
||||
** ICW1: initialization, send to command port
|
||||
*/
|
||||
|
@ -79,7 +77,6 @@
|
|||
**
|
||||
** After the init sequence, can send these
|
||||
*/
|
||||
|
||||
/*
|
||||
** OCW1: interrupt mask; send to data port
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
** M - mode
|
||||
** BCD - binary or BCD counter
|
||||
*/
|
||||
|
||||
/* Frequency settings */
|
||||
#define PIT_DEFAULT_TICKS_PER_SECOND 18 // actually 18.2065Hz
|
||||
#define PIT_DEFAULT_MS_PER_TICK (1000 / PIT_DEFAULT_TICKS_PER_SECOND)
|
||||
|
@ -68,6 +67,7 @@
|
|||
#define PIT_2_RATE 0x06 // square-wave, for USART
|
||||
|
||||
/* Timer read-back */
|
||||
|
||||
#define PIT_READBACK 0xc0 // perform a read-back
|
||||
#define PIT_RB_NOT_COUNT 0x20 // don't latch the count
|
||||
#define PIT_RB_NOT_STATUS 0x10 // don't latch the status
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
** accessed (0 selects Line Control, 1 selects Divisor Latch), with the
|
||||
** remaining bits selecting fields within the indicated register.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Receiver Data Register (read-only)
|
||||
*/
|
||||
|
|
|
@ -183,7 +183,7 @@ isr_restore:
|
|||
/*
|
||||
** DEBUGGING CODE PART 1
|
||||
**
|
||||
** This code will execute during each context restore, and
|
||||
** This code will execute during each context restore, and
|
||||
** should be modified to print out whatever debugging information
|
||||
** is desired.
|
||||
**
|
||||
|
|
|
@ -319,7 +319,7 @@ int main(void)
|
|||
|
||||
/*
|
||||
** Create the initial user process
|
||||
**
|
||||
**
|
||||
** This code is largely stolen from the fork() and exec()
|
||||
** implementations in syscalls.c; if those change, this must
|
||||
** also change.
|
||||
|
|
|
@ -339,7 +339,7 @@ void pcb_zombify(register pcb_t *victim)
|
|||
**
|
||||
** Also note: it's possible that the exiting process' parent is
|
||||
** also init, which means we're letting one of zombie children
|
||||
** of the exiting process be cleaned up by init before the
|
||||
** of the exiting process be cleaned up by init before the
|
||||
** existing process itself is cleaned up by init. This will work,
|
||||
** because after init cleans up the zombie, it will loop and
|
||||
** call waitpid() again, by which time this exiting process will
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
** Location of the "user blob" in memory.
|
||||
**
|
||||
** These variables are filled in by the code in startup.S using values
|
||||
** passed to it from the bootstrap.
|
||||
** passed to it from the bootstrap.
|
||||
**
|
||||
** These are visible so that the startup code can find them.
|
||||
*/
|
||||
|
@ -503,7 +503,7 @@ static context_t *stack_setup(pcb_t *pcb, uint32_t entry, const char **args)
|
|||
** The user code was linked with a startup function that defines
|
||||
** the entry point (_start), calls main(), and then calls exit()
|
||||
** if main() returns. We need to set up the stack this way:
|
||||
**
|
||||
**
|
||||
** esp -> context <- context save area
|
||||
** ... <- context save area
|
||||
** context <- context save area
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
** Idle process: write, getpid, gettime, exit
|
||||
**
|
||||
** Reports itself, then loops forever delaying and printing a character.
|
||||
** MUST NOT SLEEP, as it must always be available in the ready queue
|
||||
** MUST NOT SLEEP, as it must always be available in the ready queue
|
||||
** when there is no other process to dispatch.
|
||||
**
|
||||
** Invoked as: idle
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#define DRIVE_USB 0x80
|
||||
|
||||
#define SECT_SIZE 512
|
||||
|
||||
char *progname; /* invocation name of this program */
|
||||
char *bootstrap_filename; /* path of file holding bootstrap program */
|
||||
char *output_filename; /* path of disk image file */
|
||||
|
@ -45,9 +44,7 @@ short drive = DRIVE_USB; /* boot drive */
|
|||
** device) are the only limiting factors on how many program sections
|
||||
** can be loaded.
|
||||
*/
|
||||
|
||||
#define N_INFO (SECT_SIZE / sizeof(short))
|
||||
|
||||
short info[N_INFO];
|
||||
int n_info = N_INFO;
|
||||
|
||||
|
@ -69,6 +66,7 @@ void quit(char *msg, int call_perror)
|
|||
errno = err_num;
|
||||
if (call_perror) {
|
||||
perror(msg);
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
}
|
||||
|
@ -77,9 +75,9 @@ void quit(char *msg, int call_perror)
|
|||
unlink(output_filename);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
// NOTREACHED
|
||||
}
|
||||
|
||||
const char usage_error_msg[] =
|
||||
"\nUsage: %s [ -d drive ] -b bootfile -o outfile { progfile loadpt } "
|
||||
"...\n\n"
|
||||
|
@ -100,6 +98,7 @@ void usage_error(void)
|
|||
{
|
||||
fprintf(stderr, usage_error_msg, progname);
|
||||
quit(NULL, FALSE);
|
||||
|
||||
// NOTREACHED
|
||||
}
|
||||
|
||||
|
@ -127,7 +126,6 @@ int copy_file(FILE *in)
|
|||
// pad this sector out to block size
|
||||
if (n_bytes < sizeof(buf)) {
|
||||
int i;
|
||||
|
||||
for (i = n_bytes; i < sizeof(buf); i += 1) {
|
||||
buf[i] = '\0';
|
||||
}
|
||||
|
@ -180,25 +178,24 @@ void process_file(char *name, char *addr)
|
|||
if (strlen(addr) == 9 && cp == addr + 4) {
|
||||
char *ep1, *ep2;
|
||||
int a1, a2;
|
||||
|
||||
segment = strtol(addr, &ep1, 16);
|
||||
offset = strtol(addr + 5, &ep2, 16);
|
||||
address = (segment << 4) + offset;
|
||||
valid_address = *ep1 == '\0' && *ep2 == '\0';
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "Bad address format - '%s'\n", addr);
|
||||
quit(NULL, FALSE);
|
||||
}
|
||||
|
||||
} else {
|
||||
// just a number, possibly hex or octal
|
||||
char *ep;
|
||||
|
||||
address = strtol(addr, &ep, 0);
|
||||
segment = (short)(address >> 4);
|
||||
offset = (short)(address & 0xf);
|
||||
valid_address = *ep == '\0' && address <= 0x0009ffff;
|
||||
}
|
||||
|
||||
if (!valid_address) {
|
||||
fprintf(stderr, "%s: Invalid address: %s\n", progname, addr);
|
||||
quit(NULL, FALSE);
|
||||
|
@ -212,7 +209,6 @@ void process_file(char *name, char *addr)
|
|||
(unsigned int)address);
|
||||
quit(NULL, FALSE);
|
||||
}
|
||||
|
||||
if (n_info < 3) {
|
||||
quit("Too many programs!", FALSE);
|
||||
}
|
||||
|
@ -222,7 +218,6 @@ void process_file(char *name, char *addr)
|
|||
*/
|
||||
fprintf(stderr, " %s: %d sectors, loaded at 0x%x\n", name, n_sectors,
|
||||
(unsigned int)address);
|
||||
|
||||
info[--n_info] = n_sectors;
|
||||
info[--n_info] = segment;
|
||||
info[--n_info] = offset;
|
||||
|
@ -231,7 +226,6 @@ void process_file(char *name, char *addr)
|
|||
/*
|
||||
** Global variables set by getopt()
|
||||
*/
|
||||
|
||||
extern int optind, optopt;
|
||||
extern char *optarg;
|
||||
|
||||
|
@ -244,21 +238,17 @@ extern char *optarg;
|
|||
void process_args(int ac, char **av)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getopt(ac, av, ":d:o:b:")) != EOF) {
|
||||
switch (c) {
|
||||
case ':': /* missing arg value */
|
||||
fprintf(stderr, "missing operand after -%c\n", optopt);
|
||||
/* FALL THROUGH */
|
||||
|
||||
case '?': /* error */
|
||||
/* FALL THROUGH */ case '?': /* error */
|
||||
usage_error();
|
||||
/* NOTREACHED */
|
||||
|
||||
case 'b': /* -b bootstrap_file */
|
||||
/* NOTREACHED */ case 'b': /* -b bootstrap_file */
|
||||
bootstrap_filename = optarg;
|
||||
break;
|
||||
|
||||
case 'd': /* -d drive */
|
||||
switch (*optarg) {
|
||||
case 'f':
|
||||
|
@ -271,21 +261,17 @@ void process_args(int ac, char **av)
|
|||
usage_error();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o': /* -o output_file */
|
||||
output_filename = optarg;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage_error();
|
||||
}
|
||||
}
|
||||
|
||||
if (!bootstrap_filename) {
|
||||
fprintf(stderr, "%s: no bootstrap file specified\n", progname);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (!output_filename) {
|
||||
fprintf(stderr, "%s: no disk image file specified\n", progname);
|
||||
exit(2);
|
||||
|
@ -326,6 +312,7 @@ int main(int ac, char **av)
|
|||
progname = strrchr(av[0], '/');
|
||||
if (progname != NULL) {
|
||||
progname++;
|
||||
|
||||
} else {
|
||||
progname = av[0];
|
||||
}
|
||||
|
@ -338,7 +325,6 @@ int main(int ac, char **av)
|
|||
/*
|
||||
** Open the output file
|
||||
*/
|
||||
|
||||
out = fopen(output_filename, "wb+");
|
||||
if (out == NULL) {
|
||||
quit(output_filename, TRUE);
|
||||
|
@ -358,7 +344,6 @@ int main(int ac, char **av)
|
|||
*/
|
||||
int n_sectors = copy_file(bootimage);
|
||||
fclose(bootimage);
|
||||
|
||||
bootimage_size = n_sectors * SECT_SIZE;
|
||||
fprintf(stderr, " %s: %d sectors\n", bootstrap_filename, n_sectors);
|
||||
|
||||
|
@ -414,8 +399,6 @@ int main(int ac, char **av)
|
|||
*/
|
||||
fseek(out, 508, SEEK_SET);
|
||||
fwrite((void *)&drive, sizeof(drive), 1, out);
|
||||
|
||||
fclose(out);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
**
|
||||
** Examine a binary blob of ELF files.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include <ctype.h>
|
||||
#include <elf.h>
|
||||
|
@ -39,11 +40,11 @@
|
|||
** size Size of this ELF file, in bytes
|
||||
** flags Flags related to this file
|
||||
*/
|
||||
|
||||
// blob header: 8 bytes
|
||||
typedef struct header_s {
|
||||
char magic[4];
|
||||
uint32_t num;
|
||||
|
||||
} header_t;
|
||||
|
||||
// The program table entry is 32 bytes long. To accomplish this, the
|
||||
|
@ -72,8 +73,8 @@ typedef struct prog_s {
|
|||
typedef struct node_s {
|
||||
prog_t *data;
|
||||
struct node_s *next;
|
||||
} node_t;
|
||||
|
||||
} node_t;
|
||||
node_t *progs, *last_prog; // list pointers
|
||||
uint32_t n_progs; // number of files being copied
|
||||
uint32_t offset; // current file area offset
|
||||
|
@ -128,12 +129,11 @@ void process(uint32_t num, prog_t *prog)
|
|||
char *slash = strrchr(prog->name, '/');
|
||||
if (slash == NULL) {
|
||||
slash = prog->name;
|
||||
|
||||
} else {
|
||||
++slash;
|
||||
}
|
||||
|
||||
slash[0] = toupper(slash[0]);
|
||||
|
||||
if (defs) {
|
||||
// just printing #define statements
|
||||
printf("#define %-15s %2d\n", prog->name, num);
|
||||
|
@ -144,6 +144,7 @@ void process(uint32_t num, prog_t *prog)
|
|||
// first one, so print the file header
|
||||
puts(header);
|
||||
putchar('\t');
|
||||
|
||||
} else {
|
||||
// second or later entry; limit to 8 per line
|
||||
fputs(((num & 0x7) == 0) ? ",\n\t" : ", ", stdout);
|
||||
|
@ -159,65 +160,56 @@ void process(uint32_t num, prog_t *prog)
|
|||
prog->size, prog->flags);
|
||||
}
|
||||
}
|
||||
|
||||
void usage(char *name)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-d | -e] blob_name\n", name);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2 || argc > 3) {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int nameix = 1;
|
||||
|
||||
// could use getopt() for this, but this is easy enough
|
||||
if (argc == 3) {
|
||||
if (strcmp(argv[1], "-d") == 0) {
|
||||
defs = true;
|
||||
|
||||
} else if (strcmp(argv[1], "-e") == 0) {
|
||||
enums = true;
|
||||
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
nameix = 2;
|
||||
}
|
||||
|
||||
char *name = argv[nameix];
|
||||
|
||||
int fd = open(name, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror(name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
header_t hdr;
|
||||
|
||||
int n = read(fd, &hdr, sizeof(header_t));
|
||||
if (n != sizeof(header_t)) {
|
||||
fprintf(stderr, "%s: header read returned only %d bytes\n", name, n);
|
||||
close(fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(hdr.magic, "BLB") != 0) {
|
||||
fprintf(stderr, "%s: bad magic number\n", name);
|
||||
close(fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (hdr.num < 1) {
|
||||
fprintf(stderr, "%s: no programs in blob?\n", name);
|
||||
close(fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
prog_t progs[hdr.num];
|
||||
|
||||
n = read(fd, progs, hdr.num * sizeof(prog_t));
|
||||
if (n != (int)(hdr.num * sizeof(prog_t))) {
|
||||
fprintf(stderr, "%s: prog table only %d bytes, expected %lu\n", name, n,
|
||||
|
@ -225,16 +217,13 @@ int main(int argc, char *argv[])
|
|||
close(fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < hdr.num; ++i) {
|
||||
process(i, &progs[i]);
|
||||
}
|
||||
|
||||
if (enums) {
|
||||
// print the file trailer
|
||||
puts(trailer);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
**
|
||||
** Create a binary blob from a collection of ELF files.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <elf.h>
|
||||
|
@ -38,11 +39,11 @@
|
|||
** size Size of this ELF file, in bytes
|
||||
** flags Flags related to this file
|
||||
*/
|
||||
|
||||
// blob header
|
||||
typedef struct header_s {
|
||||
char magic[4];
|
||||
uint32_t num;
|
||||
|
||||
} header_t;
|
||||
|
||||
// length of the file name field
|
||||
|
@ -67,8 +68,8 @@ typedef struct node_s {
|
|||
prog_t *data;
|
||||
char *fullname;
|
||||
struct node_s *next;
|
||||
} node_t;
|
||||
|
||||
} node_t;
|
||||
node_t *progs, *last_prog; // list pointers
|
||||
uint32_t n_progs; // number of files being copied
|
||||
uint32_t offset; // current file area offset
|
||||
|
@ -114,12 +115,10 @@ void process(const char *name)
|
|||
Elf32_Ehdr hdr;
|
||||
int n = read(fd, &hdr, sizeof(Elf32_Ehdr));
|
||||
close(fd);
|
||||
|
||||
if (n != sizeof(Elf32_Ehdr)) {
|
||||
fprintf(stderr, "%s: header read was short - only %d\n", name, n);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hdr.e_ident[EI_MAG0] != ELFMAG0 || hdr.e_ident[EI_MAG1] != ELFMAG1 ||
|
||||
hdr.e_ident[EI_MAG2] != ELFMAG2 || hdr.e_ident[EI_MAG3] != ELFMAG3) {
|
||||
fprintf(stderr, "%s: bad ELF magic number\n", name);
|
||||
|
@ -132,14 +131,12 @@ void process(const char *name)
|
|||
fprintf(stderr, "%s: calloc prog returned NULL\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
node_t *node = calloc(1, sizeof(node_t));
|
||||
if (node == NULL) {
|
||||
free(new);
|
||||
fprintf(stderr, "%s: calloc node returned NULL\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
node->data = new;
|
||||
node->fullname = strdup(name);
|
||||
|
||||
|
@ -150,11 +147,11 @@ void process(const char *name)
|
|||
if (slash == NULL) {
|
||||
// only the file name
|
||||
slash = name;
|
||||
|
||||
} else {
|
||||
// skip the slash
|
||||
++slash;
|
||||
}
|
||||
|
||||
strncpy(new->name, slash, sizeof(new->name) - 1);
|
||||
new->offset = offset;
|
||||
new->size = info.st_size;
|
||||
|
@ -167,6 +164,7 @@ void process(const char *name)
|
|||
if ((info.st_size & FSIZE_MASK) != 0) {
|
||||
// nope, so we must round it up when we write it out
|
||||
new->flags |= FL_ROUNDUP;
|
||||
|
||||
// increases the offset to the next file
|
||||
offset += 8 - (info.st_size & FSIZE_MASK);
|
||||
}
|
||||
|
@ -175,6 +173,7 @@ void process(const char *name)
|
|||
if (progs == NULL) {
|
||||
// first entry
|
||||
progs = node;
|
||||
|
||||
} else {
|
||||
// add to the end
|
||||
if (last_prog == NULL) {
|
||||
|
@ -207,23 +206,24 @@ void copy(FILE *ofd, node_t *node)
|
|||
perror(node->fullname);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t buf[512];
|
||||
|
||||
// copy it block-by-block
|
||||
do {
|
||||
int n = read(fd, buf, 512);
|
||||
|
||||
// no bytes --> we're done
|
||||
if (n < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
// copy it, and verify the copy count
|
||||
int k = fwrite(buf, 1, n, ofd);
|
||||
if (k != n) {
|
||||
fprintf(stderr, "%s: write of %d returned %d\n", prog->name, n, k);
|
||||
}
|
||||
} while (1);
|
||||
|
||||
} while (1);
|
||||
printf("%s: copied %d", prog->name, prog->size);
|
||||
|
||||
// do we need to round up?
|
||||
|
@ -249,14 +249,12 @@ void copy(FILE *ofd, node_t *node)
|
|||
// all done!
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// construct program list
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
process(argv[i]);
|
||||
}
|
||||
|
||||
if (n_progs < 1) {
|
||||
fputs("Nothing to do... exiting.", stderr);
|
||||
exit(0);
|
||||
|
@ -269,14 +267,12 @@ int main(int argc, char *argv[])
|
|||
perror("user.img");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Processing %d ELF files\n", n_progs);
|
||||
|
||||
// we need to adjust the offset values so they are relative to the
|
||||
// start of the blob, not relative to the start of the file area.
|
||||
// do this by adding the sum of the file header and program entries
|
||||
// to each offset field.
|
||||
|
||||
uint32_t hlen = sizeof(header_t) + n_progs * sizeof(prog_t);
|
||||
node_t *curr = progs;
|
||||
while (curr != NULL) {
|
||||
|
@ -314,8 +310,6 @@ int main(int argc, char *argv[])
|
|||
free(tmp->fullname);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
fclose(ofd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue