cregit-Linux how code gets into the kernel

Release 4.14 arch/sparc/boot/piggyback.c

Directory: arch/sparc/boot
/*
   Simple utility to make a single-image install kernel with initial ramdisk
   for Sparc tftpbooting without need to set up nfs.

   Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000.
   Copyright (C) 2011 Sam Ravnborg <sam@ravnborg.org>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>

#include <sys/types.h>
#include <sys/stat.h>

/*
 * Note: run this on an a.out kernel (use elftoaout for it),
 * as PROM looks for a.out image only.
 */


#define AOUT_TEXT_OFFSET   32


static int is64bit = 0;

/* align to power-of-two size */

static int align(int n) { if (is64bit) return (n + 0x1fff) & ~0x1fff; else return (n + 0xfff) & ~0xfff; }

Contributors

PersonTokensPropCommitsCommitProp
Sam Ravnborg34100.00%1100.00%
Total34100.00%1100.00%

/* read two bytes as big endian */
static unsigned short ld2(char *p) { return (p[0] << 8) | p[1]; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2596.15%150.00%
Josh Triplett13.85%150.00%
Total26100.00%2100.00%

/* save 4 bytes as big endian */
static void st4(char *p, unsigned int x) { p[0] = x >> 24; p[1] = x >> 16; p[2] = x >> 8; p[3] = x; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4797.92%150.00%
Josh Triplett12.08%150.00%
Total48100.00%2100.00%


static void die(const char *str) { perror(str); exit(1); }

Contributors

PersonTokensPropCommitsCommitProp
Sam Ravnborg21100.00%1100.00%
Total21100.00%1100.00%


static void usage(void) { /* fs_img.gz is an image of initial ramdisk. */ fprintf(stderr, "Usage: piggyback bits vmlinux.aout System.map fs_img.gz\n"); fprintf(stderr, "\tKernel image will be modified in place.\n"); exit(1); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2692.86%133.33%
Sam Ravnborg13.57%133.33%
Josh Triplett13.57%133.33%
Total28100.00%3100.00%


static int start_line(const char *line) { if (strcmp(line + 10, " _start\n") == 0) return 1; else if (strcmp(line + 18, " _start\n") == 0) return 1; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Sam Ravnborg3370.21%125.00%
Linus Torvalds (pre-git)919.15%125.00%
David S. Miller48.51%125.00%
Josh Triplett12.13%125.00%
Total47100.00%4100.00%


static int end_line(const char *line) { if (strcmp(line + 10, " _end\n") == 0) return 1; else if (strcmp (line + 18, " _end\n") == 0) return 1; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Sam Ravnborg4391.49%150.00%
David S. Miller48.51%150.00%
Total47100.00%2100.00%

/* * Find address for start and end in System.map. * The file looks like this: * f0004000 ... _start * f0379f79 ... _end * 1234567890123456 * ^coloumn 1 * There is support for 64 bit addresses too. * * Return 0 if either start or end is not found */
static int get_start_end(const char *filename, unsigned int *start, unsigned int *end) { FILE *map; char buffer[1024]; *start = 0; *end = 0; map = fopen(filename, "r"); if (!map) die(filename); while (fgets(buffer, 1024, map)) { if (start_line(buffer)) *start = strtoul(buffer, NULL, 16); else if (end_line(buffer)) *end = strtoul(buffer, NULL, 16); } fclose (map); if (*start == 0 || *end == 0) return 0; return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Sam Ravnborg13297.78%150.00%
Linus Torvalds (pre-git)32.22%150.00%
Total135100.00%2100.00%

#define LOOKBACK (128 * 4) #define BUFSIZE 1024 /* * Find the HdrS entry from head_32/head_64. * We check if it is at the beginning of the file (sparc64 case) * and if not we search for it. * When we search do so in steps of 4 as HdrS is on a 4-byte aligned * address (it is on same alignment as sparc instructions) * Return the offset to the HdrS entry (as off_t) */
static off_t get_hdrs_offset(int kernelfd, const char *filename) { char buffer[BUFSIZE]; off_t offset; int i; if (lseek(kernelfd, 0, SEEK_SET) < 0) die("lseek"); if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) die(filename); if (buffer[40] == 'H' && buffer[41] == 'd' && buffer[42] == 'r' && buffer[43] == 'S') { return 40; } else { /* Find the gokernel label */ /* Decode offset from branch instruction */ offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2; /* Go back 512 bytes so we do not miss HdrS */ offset -= LOOKBACK; /* skip a.out header */ offset += AOUT_TEXT_OFFSET; if (lseek(kernelfd, offset, SEEK_SET) < 0) die("lseek"); if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) die(filename); for (i = 0; i < LOOKBACK; i += 4) { if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' && buffer[i + 2] == 'r' && buffer[i + 3] == 'S') { return offset + i; } } } fprintf (stderr, "Couldn't find headers signature in %s\n", filename); exit(1); }

Contributors

PersonTokensPropCommitsCommitProp
Sam Ravnborg236100.00%1100.00%
Total236100.00%1100.00%


int main(int argc,char **argv) { static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; char buffer[1024]; unsigned int i, start, end; off_t offset; struct stat s; int image, tail; if (argc != 5) usage(); if (strcmp(argv[1], "64") == 0) is64bit = 1; if (stat (argv[4], &s) < 0) die(argv[4]); if (!get_start_end(argv[3], &start, &end)) { fprintf(stderr, "Could not determine start and end from %s\n", argv[3]); exit(1); } if ((image = open(argv[2], O_RDWR)) < 0) die(argv[2]); if (read(image, buffer, 512) != 512) die(argv[2]); if (memcmp(buffer, aout_magic, 4) != 0) { fprintf (stderr, "Not a.out. Don't blame me.\n"); exit(1); } /* * We need to fill in values for * sparc_ramdisk_image + sparc_ramdisk_size * To locate these symbols search for the "HdrS" text which appear * in the image a little before the gokernel symbol. * See definition of these in init_32.S */ offset = get_hdrs_offset(image, argv[2]); /* skip HdrS + LINUX_VERSION_CODE + HdrS version */ offset += 10; if (lseek(image, offset, 0) < 0) die("lseek"); /* * root_flags = 0 * root_dev = 1 (RAMDISK_MAJOR) * ram_flags = 0 * sparc_ramdisk_image = "PAGE aligned address after _end") * sparc_ramdisk_size = size of image */ st4(buffer, 0); st4(buffer + 4, 0x01000000); st4(buffer + 8, align(end + 32)); st4(buffer + 12, s.st_size); if (write(image, buffer + 2, 14) != 14) die(argv[2]); /* For sparc64 update a_text and clear a_data + a_bss */ if (is64bit) { if (lseek(image, 4, 0) < 0) die("lseek"); /* a_text */ st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) + s.st_size); /* a_data */ st4(buffer + 4, 0); /* a_bss */ st4(buffer + 8, 0); if (write(image, buffer, 12) != 12) die(argv[2]); } /* seek page aligned boundary in the image file and add boot image */ if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0) die("lseek"); if ((tail = open(argv[4], O_RDONLY)) < 0) die(argv[4]); while ((i = read(tail, buffer, 1024)) > 0) if (write(image, buffer, i) != i) die(argv[2]); if (close(image) < 0) die("close"); if (close(tail) < 0) die("close"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)39073.58%444.44%
Sam Ravnborg14026.42%555.56%
Total530100.00%9100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Sam Ravnborg67155.59%650.00%
Linus Torvalds (pre-git)52343.33%433.33%
David S. Miller90.75%18.33%
Josh Triplett40.33%18.33%
Total1207100.00%12100.00%
Directory: arch/sparc/boot
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.