// Copyright 2016 The Fuchsia Authors // Copyright (c) 2013 Google, Inc. // // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT #include #include #include #include #include #include /* generated for us */ #include /* ARCH, PLATFORM, TARGET, PROJECT should be defined by the build system */ /* BUILDID is optional, and may be defined anywhere */ #ifndef BUILDID #define BUILDID "" #endif // If the build ID were SHA256, it would be 32 bytes. // (The algorithms used for build IDs today actually produce fewer than that.) // This string needs 2 bytes to print each byte in hex, plus a NUL terminator. static char elf_build_id_string[65]; const lk_version_t version = { .struct_version = VERSION_STRUCT_VERSION, .arch = ARCH, .platform = PLATFORM, .target = TARGET, .project = PROJECT, .buildid = BUILDID, .elf_build_id = elf_build_id_string, }; void print_version(void) { printf("version:\n"); printf("\tarch: %s\n", version.arch); printf("\tplatform: %s\n", version.platform); printf("\ttarget: %s\n", version.target); printf("\tproject: %s\n", version.project); printf("\tbuildid: %s\n", version.buildid); printf("\tELF build ID: %s\n", version.elf_build_id); } // Standard ELF note layout (Elf{32,64}_Nhdr in ). // The name and type fields' values are what GNU and GNU-compatible // tools (i.e. everything in the Unix-like world in recent years) // specify for build ID notes. struct build_id_note { uint32_t namesz; uint32_t descsz; uint32_t type; #define NT_GNU_BUILD_ID 3 #define NOTE_NAME "GNU" char name[(sizeof(NOTE_NAME) + 3) & -4]; uint8_t id[]; }; extern const struct build_id_note __build_id_note_start; extern const uint8_t __build_id_note_end[]; static void init_build_id(uint level) { const struct build_id_note* const note = &__build_id_note_start; if (note->type != NT_GNU_BUILD_ID || note->namesz != sizeof(NOTE_NAME) || memcmp(note->name, NOTE_NAME, sizeof(NOTE_NAME)) != 0 || ¬e->id[note->descsz] != __build_id_note_end) { panic("ELF build ID note has bad format!\n"); } if (note->descsz * 2 >= sizeof(elf_build_id_string)) { panic("ELF build ID is %u bytes, expected %u or fewer\n", note->descsz, (uint32_t)(sizeof(elf_build_id_string) / 2)); } for (uint32_t i = 0; i < note->descsz; ++i) { snprintf(&elf_build_id_string[i * 2], 3, "%02x", note->id[i]); } } // This must happen before print_version, below. LK_INIT_HOOK(elf_build_id, &init_build_id, LK_INIT_LEVEL_HEAP - 2); #include #include static int cmd_version(int argc, const cmd_args* argv, uint32_t flags) { print_version(); return 0; } STATIC_COMMAND_START STATIC_COMMAND("version", "print version", &cmd_version) STATIC_COMMAND_END(version); #if LK_DEBUGLEVEL > 0 static void print_version_init(uint) { print_version(); } // print the version string if any level of debug is set LK_INIT_HOOK(version, print_version_init, LK_INIT_LEVEL_HEAP - 1); #endif