1// Copyright 2016 The Fuchsia Authors 2// Copyright (c) 2013 Google, Inc. 3// 4// Use of this source code is governed by a MIT-style 5// license that can be found in the LICENSE file or at 6// https://opensource.org/licenses/MIT 7 8#include <lib/version.h> 9 10#include <debug.h> 11#include <lk/init.h> 12#include <stdint.h> 13#include <stdio.h> 14#include <string.h> 15 16/* generated for us */ 17#include <config-buildid.h> 18 19/* ARCH, PLATFORM, TARGET, PROJECT should be defined by the build system */ 20 21/* BUILDID is optional, and may be defined anywhere */ 22#ifndef BUILDID 23#define BUILDID "" 24#endif 25 26// If the build ID were SHA256, it would be 32 bytes. 27// (The algorithms used for build IDs today actually produce fewer than that.) 28// This string needs 2 bytes to print each byte in hex, plus a NUL terminator. 29static char elf_build_id_string[65]; 30 31const lk_version_t version = { 32 .struct_version = VERSION_STRUCT_VERSION, 33 .arch = ARCH, 34 .platform = PLATFORM, 35 .target = TARGET, 36 .project = PROJECT, 37 .buildid = BUILDID, 38 .elf_build_id = elf_build_id_string, 39}; 40 41void print_version(void) { 42 printf("version:\n"); 43 printf("\tarch: %s\n", version.arch); 44 printf("\tplatform: %s\n", version.platform); 45 printf("\ttarget: %s\n", version.target); 46 printf("\tproject: %s\n", version.project); 47 printf("\tbuildid: %s\n", version.buildid); 48 printf("\tELF build ID: %s\n", version.elf_build_id); 49} 50 51// Standard ELF note layout (Elf{32,64}_Nhdr in <elf.h>). 52// The name and type fields' values are what GNU and GNU-compatible 53// tools (i.e. everything in the Unix-like world in recent years) 54// specify for build ID notes. 55struct build_id_note { 56 uint32_t namesz; 57 uint32_t descsz; 58 uint32_t type; 59#define NT_GNU_BUILD_ID 3 60#define NOTE_NAME "GNU" 61 char name[(sizeof(NOTE_NAME) + 3) & -4]; 62 uint8_t id[]; 63}; 64 65extern const struct build_id_note __build_id_note_start; 66extern const uint8_t __build_id_note_end[]; 67 68static void init_build_id(uint level) { 69 const struct build_id_note* const note = &__build_id_note_start; 70 if (note->type != NT_GNU_BUILD_ID || 71 note->namesz != sizeof(NOTE_NAME) || 72 memcmp(note->name, NOTE_NAME, sizeof(NOTE_NAME)) != 0 || 73 ¬e->id[note->descsz] != __build_id_note_end) { 74 panic("ELF build ID note has bad format!\n"); 75 } 76 if (note->descsz * 2 >= sizeof(elf_build_id_string)) { 77 panic("ELF build ID is %u bytes, expected %u or fewer\n", 78 note->descsz, (uint32_t)(sizeof(elf_build_id_string) / 2)); 79 } 80 for (uint32_t i = 0; i < note->descsz; ++i) { 81 snprintf(&elf_build_id_string[i * 2], 3, "%02x", note->id[i]); 82 } 83} 84 85// This must happen before print_version, below. 86LK_INIT_HOOK(elf_build_id, &init_build_id, LK_INIT_LEVEL_HEAP - 2); 87 88#include <debug.h> 89#include <lib/console.h> 90 91static int cmd_version(int argc, const cmd_args* argv, uint32_t flags) { 92 print_version(); 93 return 0; 94} 95 96STATIC_COMMAND_START 97STATIC_COMMAND("version", "print version", &cmd_version) 98STATIC_COMMAND_END(version); 99 100#if LK_DEBUGLEVEL > 0 101static void print_version_init(uint) { 102 print_version(); 103} 104 105// print the version string if any level of debug is set 106LK_INIT_HOOK(version, print_version_init, LK_INIT_LEVEL_HEAP - 1); 107#endif 108