/* $Id: fsw_efi_lib.c 98103 2023-01-17 14:15:46Z vboxsync $ */ /** @file * fsw_efi_lib.c - EFI host environment library functions. */ /* * Copyright (C) 2010-2023 Oracle and/or its affiliates. * * This file is part of VirtualBox base platform packages, as * available from https://www.virtualbox.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, in version 3 of the * License. * * 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, see . * * The contents of this file may alternatively be used under the terms * of the Common Development and Distribution License Version 1.0 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included * in the VirtualBox distribution, in which case the provisions of the * CDDL are applicable instead of those of the GPL. * * You may elect to license modified versions of this file under the * terms and conditions of either the GPL or the CDDL or both. * * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 * --------------------------------------------------------------------------- * This code is based on: * * Copyright (c) 2006 Christoph Pfisterer * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * * Neither the name of Christoph Pfisterer nor the names of the * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "fsw_efi.h" // // time conversion // // Adopted from public domain code in FreeBSD libc. // #define SECSPERMIN 60 #define MINSPERHOUR 60 #define HOURSPERDAY 24 #define DAYSPERWEEK 7 #define DAYSPERNYEAR 365 #define DAYSPERLYEAR 366 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) #define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) #define MONSPERYEAR 12 #define EPOCH_YEAR 1970 #define EPOCH_WDAY TM_THURSDAY #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) static const int mon_lengths[2][MONSPERYEAR] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; static const int year_lengths[2] = { DAYSPERNYEAR, DAYSPERLYEAR }; VOID fsw_efi_decode_time(OUT EFI_TIME *EfiTime, IN UINT32 UnixTime) { long days, rem; int y, newy, yleap; const int *ip; ZeroMem(EfiTime, sizeof(EFI_TIME)); days = UnixTime / SECSPERDAY; rem = UnixTime % SECSPERDAY; EfiTime->Hour = (UINT8) (rem / SECSPERHOUR); rem = rem % SECSPERHOUR; EfiTime->Minute = (UINT8) (rem / SECSPERMIN); EfiTime->Second = (UINT8) (rem % SECSPERMIN); y = EPOCH_YEAR; while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { newy = y + days / DAYSPERNYEAR; if (days < 0) --newy; days -= (newy - y) * DAYSPERNYEAR + LEAPS_THRU_END_OF(newy - 1) - LEAPS_THRU_END_OF(y - 1); y = newy; } EfiTime->Year = (UINT16)y; ip = mon_lengths[yleap]; for (EfiTime->Month = 0; days >= (long) ip[EfiTime->Month]; ++(EfiTime->Month)) days = days - (long) ip[EfiTime->Month]; EfiTime->Month++; // adjust range to EFI conventions EfiTime->Day = (UINT8) (days + 1); } // // String functions, used for file and volume info // UINTN fsw_efi_strsize(struct fsw_string *s) { if (s->type == FSW_STRING_TYPE_EMPTY) return sizeof(CHAR16); return (s->len + 1) * sizeof(CHAR16); } VOID fsw_efi_strcpy(CHAR16 *Dest, struct fsw_string *src) { if (src->type == FSW_STRING_TYPE_EMPTY) { Dest[0] = 0; } else if (src->type == FSW_STRING_TYPE_UTF16) { CopyMem(Dest, src->data, src->size); Dest[src->len] = 0; } else { /// @todo coerce, recurse Dest[0] = 0; } } #ifdef VBOX int fsw_streq_ISO88591_UTF16(void *s1data, void *s2data, int len) { int i; fsw_u8 *p1 = (fsw_u8 *)s1data; fsw_u16 *p2 = (fsw_u16 *)s2data; for (i = 0; i