#include "fat12.h" #include namespace esphome { namespace grub_boot_switch { static inline uint8_t fat_checksum(const char *name) { uint8_t s = name[0]; s = (s << 7) + (s >> 1) + name[1]; s = (s << 7) + (s >> 1) + name[2]; s = (s << 7) + (s >> 1) + name[3]; s = (s << 7) + (s >> 1) + name[4]; s = (s << 7) + (s >> 1) + name[5]; s = (s << 7) + (s >> 1) + name[6]; s = (s << 7) + (s >> 1) + name[7]; s = (s << 7) + (s >> 1) + name[8]; s = (s << 7) + (s >> 1) + name[9]; s = (s << 7) + (s >> 1) + name[10]; return s; } static uint8_t write_utf16_chars(const char *name, uint8_t *index, uint8_t length, uint8_t write_count, uint8_t *output) { for (uint8_t i = write_count; i != 0; --i) { if (*index <= length) { *output++ = name[*index]; *output++ = 0x00; ++(*index); } else { *output++ = 0xFF; *output++ = 0xFF; } } return write_count * 2; } uint8_t fat_write_lfn(const char *name, const FatDirEntry *direntry, uint8_t *output) { constexpr uint8_t kCharsPerEntry = 13; const size_t length = strlen(name); const uint8_t num_entries = (length + (kCharsPerEntry - 1)) / kCharsPerEntry; const uint8_t checksum = fat_checksum(reinterpret_cast(direntry)); for (uint8_t ordinal = num_entries; ordinal != 0; --ordinal) { uint8_t index = (ordinal - 1) * kCharsPerEntry; *output = ordinal | (kFat_LastLFN * (ordinal == num_entries)); ++output; output += write_utf16_chars(name, &index, length, 5, output); output[0] = kFatAttr_LongFileName; output[1] = 0x00; output[2] = checksum; output += 3; output += write_utf16_chars(name, &index, length, 6, output); output[0] = 0x00; output[1] = 0x00; output += 2; output += write_utf16_chars(name, &index, length, 2, output); } return sizeof(FatDirEntry) * num_entries; } uint8_t fat_write_dir(const FatDirEntry *direntry, uint8_t *output) { memcpy(output, direntry, sizeof(FatDirEntry)); return sizeof(FatDirEntry); } uint16_t fat_date(uint16_t year, uint8_t month, uint8_t day) { return ((year - 1980) << 9) | (month << 5) | day; } } // namespace grub_boot_switch } // namespace esphome