Ticket #5137: boot_celf.patch

File boot_celf.patch, 18.1 KB (added by Grey, 11 years ago)

Patch. Boot loading compressed kernel and drivers.

  • build/jam/ImageRules

     
    12991299    #$(RM) -R $(HAIKU_OUTPUT_DIR)/cd
    13001300}
    13011301
     1302# warning: that is x86 and linux host machine only!
    13021303
     1304rule CompressFile
     1305{
     1306    # CompressFile <file> ;
     1307    # Compress file in-place
     1308
     1309    ALWAYS $(1) ;
     1310    CompressFile1 $(1) ;
     1311}
     1312
     1313actions CompressFile1
     1314{
     1315    echo "$(HAIKU_TOP)/generated/objects/linux/$(TARGET_ARCH)/release/bin/recompress/recompres $(HAIKU_TOP)/$(1) $(HAIKU_TOP)/$(1)" >> $(HAIKU_OUTPUT_DIR)/haiku.image-copy-files
     1316}
     1317
     1318rule AddCompressedDriversToHaikuImage
     1319{
     1320    # AddCompressedDriversToHaikuImage <drivers> ;
     1321    # Compress <drivers> and add compressed <drivers> to ${tPrefix}system/add-ons/kernel/boot
     1322
     1323    ALWAYS $(1) ;
     1324    AddCompressedDriversToHaikuImage1 $(1) ;
     1325}
     1326
     1327actions AddCompressedDriversToHaikuImage1
     1328{
     1329    for target in $(1)
     1330    do
     1331    echo "$(HAIKU_TOP)/generated/objects/linux/$(TARGET_ARCH)/release/bin/recompress/recompres $(HAIKU_TOP)/$target $(HAIKU_TOP)/$target.celf" >> $(HAIKU_OUTPUT_DIR)/haiku.image-copy-files
     1332    echo  "\$cp \"\${sPrefix}$target.celf\" \"\${tPrefix}system/add-ons/kernel/boot\"" >> $(HAIKU_OUTPUT_DIR)/haiku.image-copy-files
     1333    done
     1334}
  • build/jam/HaikuImage

     
    4949    passwd paste patch pathchk pc ping play playfile playsound playwav pr prio
    5050    printenv printf profile ps ptx pwd
    5151    query quit
    52     rc readlink reindex release renice rlog rm rmattr rmindex rmdir roster
     52    rc readlink recompress reindex release renice rlog rm rmattr rmindex rmdir roster
    5353    route
    5454    safemode screen_blanker screenmode sed setdecor settype setversion setvolume
    5555    seq sha1sum shar shred shuf shutdown sleep sort spamdbm split stat strace
     
    242242#AddDriversToHaikuImage power       : $(SYSTEM_ADD_ONS_DRIVERS_POWER) ;
    243243
    244244# kernel
     245CompressFile <revisioned>kernel_$(TARGET_ARCH) ;
    245246AddFilesToHaikuImage system : <revisioned>kernel_$(TARGET_ARCH) ;
    246247
    247248# libs
     
    474475# boot loader
    475476AddFilesToHaikuImage system : haiku_loader ;
    476477
    477 # boot module links
    478 AddBootModuleSymlinksToHaikuImage
     478# boot modules
     479AddDirectoryToHaikuImage system add-ons kernel boot ;
     480AddCompressedDriversToHaikuImage
    479481    $(X86_ONLY)acpi $(ATA_ONLY)ata pci $(X86_ONLY)isa config_manager dpc
    480482    $(IDE_ONLY)ide scsi usb
    481483    $(PPC_ONLY)openpic
  • src/system/boot/loader/elf.cpp

     
    1616#include <unistd.h>
    1717#include <string.h>
    1818#include <stdlib.h>
     19#include <zlib.h>
    1920
    2021//#define TRACE_ELF
    2122#ifdef TRACE_ELF
     
    2829static bool sLoadElfSymbols = false;
    2930
    3031
     32/* Decompress from file fd to memory dest until EOF.
     33   inflater() returns B_OK on success, B_NO_MEMORY if memory could not be
     34   allocated for processing, B_BAD_TYPE if the deflate data is
     35   invalid or incomplete.
     36*/
     37
     38#define CHUNK (16 * 1024)
     39
     40static status_t
     41inflater(int fd, char *dest, int dest_size)
     42{
     43    char in[CHUNK];
     44    z_stream strm;
     45    int ret, shift = 0;
     46
     47    // allocate inflate state
     48    strm.zalloc = Z_NULL;
     49    strm.zfree = Z_NULL;
     50    strm.opaque = Z_NULL;
     51    strm.avail_in = 0;
     52    strm.next_in = Z_NULL;
     53    ret = inflateInit(&strm);
     54    // decompress until end of file
     55    do {
     56            strm.avail_in = read(fd, in, CHUNK);
     57            if (strm.avail_in == 0) {
     58                (void)inflateEnd(&strm);
     59                return B_BAD_TYPE;
     60            }
     61            if (shift == 0 && memcmp(in + 1,"ELF",3) == 0) {
     62                memcpy((Bytef *) dest,in,strm.avail_in);
     63                if (strm.avail_in == CHUNK) {
     64                    read(fd, dest + strm.avail_in, dest_size - CHUNK);
     65                }
     66                (void)inflateEnd(&strm);
     67                return B_OK;
     68            }
     69            strm.next_in = (Bytef *) in;
     70            strm.avail_out = dest_size - shift;
     71            strm.next_out = (Bytef *) dest + shift;
     72            ret = inflate(&strm, Z_NO_FLUSH);
     73            switch (ret) {
     74                case Z_NEED_DICT:
     75                case Z_DATA_ERROR:
     76                    (void)inflateEnd(&strm);
     77                    return B_BAD_TYPE;
     78                case Z_MEM_ERROR:
     79                    (void)inflateEnd(&strm);
     80                    return B_NO_MEMORY;
     81            }
     82            shift = dest_size - strm.avail_out;
     83            if (strm.avail_out == 0) {
     84                (void)inflateEnd(&strm);
     85                return B_NO_MEMORY;
     86            }       
     87        } while (ret != Z_STREAM_END);
     88    (void)inflateEnd(&strm);
     89    return B_OK;
     90}
     91
     92
    3193void
    3294elf_init()
    3395{
     
    119181
    120182
    121183static status_t
    122 load_elf_symbol_table(int fd, preloaded_image *image)
     184load_elf_symbol_table(int fd, preloaded_image *image, char *unzip_buf)
    123185{
    124186    struct Elf32_Ehdr &elfHeader = image->elf_header;
    125187    Elf32_Sym *symbolTable = NULL;
     
    137199        return B_NO_MEMORY;
    138200    }
    139201
    140     ssize_t length = read_pos(fd, elfHeader.e_shoff, sectionHeaders, size);
    141     if (length < size) {
    142         TRACE(("error reading in program headers\n"));
    143         status = B_ERROR;
    144         goto error1;
    145     }
     202    memcpy(sectionHeaders, unzip_buf+elfHeader.e_shoff, size);
    146203
    147204    // find symbol table in section headers
    148205
     
    164221                goto error1;
    165222            }
    166223
    167             length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable,
    168                 size);
    169             if (length < size) {
    170                 TRACE(("error reading in symbol table\n"));
    171                 status = B_ERROR;
    172                 goto error1;
    173             }
     224            memcpy(symbolTable, unzip_buf + sectionHeaders[i].sh_offset, size);
    174225
    175226            numSymbols = size / sizeof(Elf32_Sym);
    176227            break;
     
    191242        goto error2;
    192243    }
    193244
    194     length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
    195     if (length < size) {
    196         TRACE(("error reading in string table\n"));
    197         status = B_ERROR;
    198         goto error3;
    199     }
     245    memcpy(stringTable, unzip_buf + stringHeader->sh_offset, size);
    200246
    201247    TRACE(("loaded %ld debug symbols\n", numSymbols));
    202248
     
    209255    free(sectionHeaders);
    210256    return B_OK;
    211257
    212 error3:
    213     kernel_args_free(stringTable);
    214258error2:
    215259    kernel_args_free(symbolTable);
    216260error1:
     
    221265
    222266
    223267status_t
    224 elf_load_image(int fd, preloaded_image *image)
     268elf_load_image(int fd, preloaded_image *image, char *unzip_buf, int unzip_buf_size)
    225269{
    226270    size_t totalSize;
    227271    status_t status;
    228272
    229273    TRACE(("elf_load_image(fd = %d, image = %p)\n", fd, image));
    230274
     275    inflater(fd, unzip_buf, unzip_buf_size );
     276
    231277    struct Elf32_Ehdr &elfHeader = image->elf_header;
    232 
    233     ssize_t length = read_pos(fd, 0, &elfHeader, sizeof(Elf32_Ehdr));
    234     if (length < (ssize_t)sizeof(Elf32_Ehdr))
    235         return B_BAD_TYPE;
    236 
     278    memcpy(&elfHeader, unzip_buf, sizeof(Elf32_Ehdr));
    237279    status = verify_elf_header(elfHeader);
    238280    if (status < B_OK)
    239281        return status;
     
    245287        return B_NO_MEMORY;
    246288    }
    247289
    248     length = read_pos(fd, elfHeader.e_phoff, programHeaders, size);
    249     if (length < size) {
    250         TRACE(("error reading in program headers\n"));
    251         status = B_ERROR;
    252         goto error1;
    253     }
     290    memcpy(programHeaders, unzip_buf + elfHeader.e_phoff, size);
    254291
    255     // create an area large enough to hold the image
    256 
    257292    image->data_region.size = 0;
    258293    image->text_region.size = 0;
    259294
     
    361396
    362397        TRACE(("load segment %d (%ld bytes)...\n", i, header.p_filesz));
    363398
    364         length = read_pos(fd, header.p_offset,
    365             (void *)(region->start + (header.p_vaddr % B_PAGE_SIZE)),
    366             header.p_filesz);
    367         if (length < (ssize_t)header.p_filesz) {
    368             status = B_BAD_DATA;
    369             dprintf("error reading in seg %d\n", i);
    370             goto error2;
    371         }
     399        memcpy((void *)(region->start + (header.p_vaddr % B_PAGE_SIZE)),
     400                unzip_buf + header.p_offset,
     401                header.p_filesz);
    372402
    373403        // Clear anything above the file size (that may also contain the BSS
    374404        // area)
     
    388418    image->debug_string_table = NULL;
    389419
    390420    if (sLoadElfSymbols)
    391         load_elf_symbol_table(fd, image);
     421        load_elf_symbol_table(fd, image, unzip_buf);
    392422
    393423    free(programHeaders);
    394424
    395425    return B_OK;
    396426
    397 error2:
    398     if (image->text_region.start != 0)
    399         platform_free_region((void *)image->text_region.start, totalSize);
    400427error1:
    401428    free(programHeaders);
    402429
     
    405432
    406433
    407434status_t
    408 elf_load_image(Directory *directory, const char *path)
     435elf_load_image(Directory *directory, const char *path, char *unzip_buf, int unzip_buf_size)
    409436{
    410437    preloaded_image *image;
    411438
     
    437464        return B_NO_MEMORY;
    438465    }
    439466
    440     status_t status = elf_load_image(fd, image);
     467    status_t status = elf_load_image(fd, image, unzip_buf, unzip_buf_size);
    441468    if (status == B_OK) {
    442469        image->name = kernel_args_strdup(path);
    443470        image->inode = stat.st_ino;
  • src/system/boot/loader/loader.cpp

     
    5252
    5353
    5454status_t
    55 load_kernel(stage2_args *args, Directory *volume)
     55load_kernel(stage2_args *args, Directory *volume, char *unzip_buf, int unzip_buf_size)
    5656{
    5757    int fd = open_from(volume, KERNEL_PATH, O_RDONLY);
    5858    if (fd < B_OK)
     
    6161    dprintf("load kernel...\n");
    6262
    6363    elf_init();
    64     status_t status = elf_load_image(fd, &gKernelArgs.kernel_image);
     64    status_t status = elf_load_image(fd, &gKernelArgs.kernel_image, unzip_buf, unzip_buf_size);
    6565
    6666    close(fd);
    6767
     
    8383
    8484
    8585static status_t
    86 load_modules_from(Directory *volume, const char *path)
     86load_modules_from(Directory *volume, const char *path, char *unzip_buf, int unzip_buf_size)
    8787{
    8888    // we don't have readdir() & co. (yet?)...
    8989
     
    102102            if (!strcmp(name, ".") || !strcmp(name, ".."))
    103103                continue;
    104104
    105             status_t status = elf_load_image(modules, name);
     105            status_t status = elf_load_image(modules, name, unzip_buf, unzip_buf_size);
    106106            if (status != B_OK)
    107107                dprintf("Could not load \"%s\" error %ld\n", name, status);
    108108        }
     
    121121 */
    122122
    123123static status_t
    124 load_module(Directory *volume, const char *name)
     124load_module(Directory *volume, const char *name, char *unzip_buf, int unzip_buf_size)
    125125{
    126126    char moduleName[B_FILE_NAME_LENGTH];
    127127    if (strlcpy(moduleName, name, sizeof(moduleName)) > sizeof(moduleName))
     
    142142                if (fstat(fd, &stat) != 0 || !S_ISREG(stat.st_mode))
    143143                    return B_BAD_VALUE;
    144144
    145                 status_t status = elf_load_image(base, moduleName);
     145                status_t status = elf_load_image(base, moduleName, unzip_buf, unzip_buf_size);
    146146
    147147                close(fd);
    148148                close(baseFD);
     
    166166
    167167
    168168status_t
    169 load_modules(stage2_args *args, Directory *volume)
     169load_modules(stage2_args *args, Directory *volume, char *unzip_buf, int unzip_buf_size)
    170170{
    171171    int32 failed = 0;
    172172
     
    176176        char path[B_FILE_NAME_LENGTH];
    177177        sprintf(path, "%s/boot", sPaths[i]);
    178178
    179         if (load_modules_from(volume, path) != B_OK)
     179        if (load_modules_from(volume, path, unzip_buf, unzip_buf_size) != B_OK)
    180180            failed++;
    181181    }
    182182
     
    189189        for (int32 i = 0; paths[i]; i++) {
    190190            char path[B_FILE_NAME_LENGTH];
    191191            sprintf(path, "%s/%s", sPaths[0], paths[i]);
    192             load_modules_from(volume, path);
     192            load_modules_from(volume, path, unzip_buf, unzip_buf_size);
    193193        }
    194194    }
    195195
     
    202202        Partition *partition;
    203203        if (gRoot->GetPartitionFor(volume, &partition) == B_OK) {
    204204            while (partition != NULL) {
    205                 load_module(volume, partition->ModuleName());
     205                load_module(volume, partition->ModuleName(), unzip_buf, unzip_buf_size);
    206206                partition = partition->Parent();
    207207            }
    208208        }
     
    214214        //  loading approach...
    215215        char path[B_FILE_NAME_LENGTH];
    216216        sprintf(path, "%s/%s", sPaths[0], "file_systems");
    217         load_modules_from(volume, path);
     217        load_modules_from(volume, path, unzip_buf, unzip_buf_size);
    218218    }
    219219
    220220    return B_OK;
  • src/system/boot/loader/elf.h

     
    1111
    1212
    1313extern void elf_init();
    14 extern status_t elf_load_image(Directory *directory, const char *path);
    15 extern status_t elf_load_image(int fd, preloaded_image *image);
     14extern status_t elf_load_image(Directory *directory, const char *path, char *unzip_buf, int unzip_buf_size);
     15extern status_t elf_load_image(int fd, preloaded_image *image, char *unzip_buf, int unzip_buf_size);
    1616
    1717extern status_t elf_relocate_image(struct preloaded_image *image);
    1818
  • src/system/boot/loader/loader.h

     
    1010
    1111
    1212extern bool is_bootable(Directory *volume);
    13 extern status_t load_kernel(stage2_args *args, Directory *volume);
    14 extern status_t load_modules(stage2_args *args, Directory *volume);
     13extern status_t load_kernel(stage2_args *args, Directory *volume, char *unzip_buf, int unzip_buf_size);
     14extern status_t load_modules(stage2_args *args, Directory *volume, char *unzip_buf, int unzip_buf_size);
    1515
    1616#endif  /* LOADER_H */
  • src/system/boot/loader/main.cpp

     
    2424#   define TRACE(x) ;
    2525#endif
    2626
     27#define KERNEL_BUF_SIZE (4*1024*1024)
     28#define UNZIP_BUF_SIZE  (4*1024*1024)
    2729
    2830extern "C" int
    2931main(stage2_args *args)
     
    7678
    7779    if (volume != NULL) {
    7880        // we got a volume to boot from!
     81       
     82        // allocate upper memory for uncompress buffer
     83        char *kernel_buf = (char *)kernel_args_malloc(KERNEL_BUF_SIZE);
     84        char *unzip_buf = (char *)kernel_args_malloc(UNZIP_BUF_SIZE);
     85        kernel_args_free(kernel_buf);
     86        if (!unzip_buf) {
     87            panic("Could not allocate memory for uncompressing kernel!\n" );
     88        }
     89
    7990        status_t status;
    80         while ((status = load_kernel(args, volume)) < B_OK) {
     91        while ((status = load_kernel(args, volume, unzip_buf, UNZIP_BUF_SIZE)) < B_OK) {
    8192            // loading the kernel failed, so let the user choose another
    8293            // volume to boot from until it works
    8394            volume = NULL;
     
    105116            if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) == 0)
    106117                platform_switch_to_logo();
    107118
    108             load_modules(args, volume);
     119            load_modules(args, volume, unzip_buf, UNZIP_BUF_SIZE);
     120            kernel_args_free(unzip_buf);
    109121            load_driver_settings(args, volume);
    110122
    111123            // set up kernel args version info
  • src/system/boot/loader/Jamfile

     
    99UsePrivateHeaders [ FDirName kernel util ] ;
    1010UsePrivateHeaders shared storage ;
    1111
     12UseHeaders [ FDirName $(HAIKU_TOP) headers libs zlib ] ;
     13SubDirSysHdrs $(HAIKU_TOP) headers libs zlib ;
     14
    1215{
    1316    local defines =
    1417        _BOOT_MODE
     
    7174    list.cpp
    7275    safemode_settings.cpp
    7376
     77    # compression
     78    crc32.c
     79    zutil.c
     80    uncompr.c
    7481    : -fno-pic
    7582    ;
    7683
     
    116123SEARCH on [ FGristFiles stage2_crt0.S ]
    117124    = [ FDirName $(HAIKU_TOP) src system boot arch $(TARGET_ARCH) ] ;
    118125
    119 
     126SEARCH on [ FGristFiles crc32.c zutil.c uncompr.c ]
     127   = [ FDirName $(HAIKU_TOP) src libs zlib ] ;
     128
    120129SubInclude HAIKU_TOP src system boot loader file_systems ;
    121130SubInclude HAIKU_TOP src system boot loader net ;
  • src/bin/Jamfile

     
    248248SubInclude HAIKU_TOP src bin gzip ;
    249249SubInclude HAIKU_TOP src bin bzip2 ;
    250250SubInclude HAIKU_TOP src bin tar ;
     251SubInclude HAIKU_TOP src bin recompress ;
  • src/bin/recompress/recompress.c

     
     1/*! Simple compress/uncompress. Use ZLIB */
     2#include <stdio.h>
     3#include <stdlib.h>
     4#include <zlib.h>
     5
     6#define MAX_FILE_SIZE (4*1024*1024)
     7
     8int
     9main(int argc, char **argv)
     10{
     11    FILE *file;
     12    char *fdata;
     13    char *ndata;
     14    unsigned long fsize, nsize;
     15    int compression_level = 6;
     16
     17    if (argc > 4 || argc < 3) {
     18        fprintf(stderr, "Compress/Uncompress file.\n");
     19        fprintf(stderr, "Usage:  recompress src_file dst_file [-123456789]\n");
     20        fprintf(stderr, "-1      low compression\n");
     21        fprintf(stderr, "-9      high compression\n");
     22        fprintf(stderr, "-6      default compression\n");
     23        return 1;
     24    }
     25
     26    if (argc == 4 && argv[3][0] == '-'
     27        && argv[3][1] > '0' && argv[3][1] <= '9' && argv[3][2] == 0) {
     28        compression_level = argv[3][1] - '0';
     29    }
     30
     31    file = fopen(argv[1], "rb");
     32    if (file == 0) {
     33        fprintf(stderr, "File not found: %s\n", argv[1]);
     34        return 2;
     35    }
     36
     37    fseek(file, 0, SEEK_END);
     38    fsize = ftell(file);
     39    fseek(file, 0, SEEK_SET);
     40
     41    fdata = malloc(fsize);
     42    ndata = malloc(10 * fsize);
     43
     44    fread(fdata, 1, MAX_FILE_SIZE, file);
     45    fclose(file);
     46
     47    nsize = MAX_FILE_SIZE;
     48    if (uncompress((Bytef *) ndata, &nsize, (Bytef *) fdata, fsize)) {
     49        // Compress uncompressed file
     50        nsize = MAX_FILE_SIZE;
     51        compress2((Bytef *) ndata, &nsize, (Bytef *) fdata, fsize,
     52                  compression_level);
     53        printf("Compressing   %s to %s", argv[1], argv[2]);
     54    } else {
     55        printf("Uncompressing %s to %s", argv[1], argv[2]);
     56    }
     57    printf("  -> %ld%% Old_size=%ld New_size=%ld\n",
     58           (200 * nsize + 1) / (2 * fsize), fsize, nsize);
     59    file = fopen(argv[2], "wb");
     60    if (file == 0) {
     61        printf("Can't create file: %s\n", argv[2]);
     62        return 3;
     63    }
     64    fwrite(ndata, nsize, 1, file);
     65    fclose(file);
     66    free(fdata);
     67    free(ndata);
     68    return 0;
     69}
     70
  • src/bin/recompress/Jamfile

     
     1SubDir HAIKU_TOP src bin recompress ;
     2
     3SetSubDirSupportedPlatformsBeOSCompatible ;
     4
     5Objects $(common_files) $(common_files2) $(util_files) ;
     6
     7UseLibraryHeaders zlib ;
     8SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src libs zlib ] ;
     9
     10SubDirCcFlags -DNOID -DHAVE_STDINT_H=0 ;
     11
     12SubDirSysHdrs [ FDirName $(SUBDIR) include ] ;
     13SubDirSysHdrs [ FDirName $(SUBDIR) lib ] ;
     14
     15Depends recompress : recompres ;
     16
     17BinCommand recompress :
     18    recompress.c
     19    compress.c
     20    uncompr.c
     21    deflate.c
     22    crc32.c
     23    adler32.c
     24    inflate.c
     25    zutil.c
     26    trees.c
     27    inffast.c
     28    inftrees.c
     29    : be
     30;
     31
     32BuildPlatformMain recompres :
     33    recompress.c
     34    compress.c
     35    uncompr.c
     36    deflate.c
     37    crc32.c
     38    adler32.c
     39    inflate.c
     40    zutil.c
     41    trees.c
     42    inffast.c
     43    inftrees.c
     44;
     45
     46