// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package bootrecord

import (
	"errors"
	"fmt"

	"go.fuchsia.dev/fuchsia/src/lib/thinfs/bitops"
)

const (
	bootSig           = 0xAA55
	bootSigExtended   = 0x29
	driveNumberDisk   = 0x80
	driveNumberFloppy = 0x00
)

// FATType describes the type of underlying filesystem described by the boot record.
type FATType int

// Identify the type of filesystem described by this boot record.
const (
	FATInvalid FATType = 0
	FAT12      FATType = 12
	FAT16      FATType = 16
	FAT32      FATType = 32
)

func bootSectorSignatureValid(sig []uint8) error {
	s := bitops.GetLE16(sig)
	if s != bootSig {
		return fmt.Errorf("Expected boot signature: %x, but got %x", bootSig, s)
	}
	return nil
}

// Shared beginning of bootsector.
type bootsectorPrefix struct {
	// Boot Sector
	jmpBoot [3]uint8 // Jump instruction 0xEB__90 or 0xE9____
	oemName [8]uint8 // Informal name of system which formatted the volume
}

func (b *bootsectorPrefix) validate() error {
	if b.jmpBoot[0] == 0xE9 {
		return nil
	}
	if b.jmpBoot[0] == 0xEB && b.jmpBoot[2] == 0x90 {
		return nil
	}
	return errors.New("Invalid jmpBoot instruction")
}

// Shared BPB fields between FAT12/16/32.
type bpbShared struct {
	bytesPerSec        [2]uint8 // 512, 1024, 2048, or 4096
	sectorsPerCluster  uint8    // Must be a power of 2 between 1 and 128
	numSectorsReserved [2]uint8 // FAT12/16: 1. FAT32: 32
	numFATs            uint8    // Greater than or equal to 1. Usually 2
	numRootEntries     [2]uint8 // FAT12/16: Root directory entries. FAT32: 0
	totalSectors16     [2]uint8 // FAT12/16: Sector count, if < 0x10000. FAT32: Always 0
	media              uint8    // Media descriptor
	sectorsPerFAT16    [2]uint8 // FAT12/16: Sectors for ONE FAT. FAT32: 0
	sectorsPerTrack    [2]uint8 // Geometry info
	numHeads           [2]uint8 // Geometry info
	numSectorsHidden   [4]uint8 // Hidden sectors preceding partition
	totalSectors32     [4]uint8 // FAT12/16: Sector count if >= 0x10000. FAT32: Sector count
}

func (b *bpbShared) BytesPerSec() uint32 {
	return uint32(bitops.GetLE16(b.bytesPerSec[:]))
}
func (b *bpbShared) SectorsPerCluster() uint32 {
	return uint32(b.sectorsPerCluster)
}
func (b *bpbShared) NumSectorsReserved() uint32 {
	return uint32(bitops.GetLE16(b.numSectorsReserved[:]))
}
func (b *bpbShared) NumFATs() uint32 {
	return uint32(b.numFATs)
}
func (b *bpbShared) NumRootEntries() uint32 {
	return uint32(bitops.GetLE16(b.numRootEntries[:]))
}
func (b *bpbShared) TotalSectors16() uint32 {
	return uint32(bitops.GetLE16(b.totalSectors16[:]))
}
func (b *bpbShared) SectorsPerFAT16() uint32 {
	return uint32(bitops.GetLE16(b.sectorsPerFAT16[:]))
}
func (b *bpbShared) SectorsPerTrack() uint32 {
	return uint32(bitops.GetLE16(b.sectorsPerTrack[:]))
}
func (b *bpbShared) NumHeads() uint32 {
	return uint32(bitops.GetLE16(b.numHeads[:]))
}
func (b *bpbShared) SectorsHidden() uint32 {
	return uint32(bitops.GetLE32(b.numSectorsHidden[:]))
}
func (b *bpbShared) TotalSectors32() uint32 {
	return uint32(bitops.GetLE32(b.totalSectors32[:]))
}
func (b *bpbShared) TotalSectors() uint32 {
	ts16 := b.TotalSectors16()
	ts32 := b.TotalSectors32()
	if ts16 != 0 {
		return ts16
	}
	return ts32
}

// Without verification, tries to guess FAT group. Returns true for FAT32, false for FAT12/16.
// Does not verify any correctness.
func (b *bpbShared) guessFATType() bool {
	return b.NumRootEntries() == 0
}

func (b *bpbShared) TotalClusters(firstDataSector uint32) uint32 {
	totalSectors := b.TotalSectors()
	sectorsPerCluster := b.SectorsPerCluster()
	numDataSectors := totalSectors - firstDataSector
	return numDataSectors / sectorsPerCluster
}

// For a detailed description of the validation occurring here, see pages 9-13 of "FAT: General
// Overview of On-Disk Format".
// The "large" argument is true if the filesystem supported by bpbShared is FAT32.
// "large" is false for FAT12 and FAT16.
func (b *bpbShared) validate(large bool) error {
	bytesPerSec := b.BytesPerSec()
	switch bytesPerSec {
	case 512, 1024, 2048, 4096:
	default:
		return fmt.Errorf("Bytes/Sector invalid: %d", bytesPerSec)
	}

	sectorsPerCluster := uint32(b.sectorsPerCluster)
	switch sectorsPerCluster {
	case 1, 2, 4, 8, 16, 32, 64, 128:
	default:
		return fmt.Errorf("Sectors/Cluster invalid: %d", sectorsPerCluster)
	}

	// Validation of both bytesPerSec and sectorsPerCluster together.
	bytesPerCluster := bytesPerSec * sectorsPerCluster
	if bytesPerCluster > 32*1024 {
		return fmt.Errorf("Byte/Cluster greater than 32K: %d", bytesPerCluster)
	}

	numSectorsReserved := b.NumSectorsReserved()
	if large && numSectorsReserved == 0 {
		return errors.New("FAT32 cannot have zero reserved sectors")
	} else if !large && numSectorsReserved != 1 {
		return errors.New("FAT12/16 cannot have any number of reserved sectors other than one")
	}

	if b.NumFATs() == 0 {
		return errors.New("NumFATs cannot be zero")
	}

	numRootEntries := b.NumRootEntries()
	if large && numRootEntries != 0 {
		return errors.New("FAT32 must set numRootEntries to zero")
	} else if !large {
		if numRootEntries == 0 {
			return errors.New("FAT12/16 must have at least one root entry")
		} else if numRootEntries*32%bytesPerSec != 0 {
			// "For FAT12 and FAT16 volumes, this value should always specify a count that when
			// multiplied by 32 results in an even multiple of BPB_BytsPerSec".
			return errors.New("NumRootEntries * 32 must be an even multiple of bytes per sector")
		}
	}

	// totalSectors16 and totalSectors32 should be evaluated together.
	totalSectors16 := b.TotalSectors16()
	totalSectors32 := b.TotalSectors32()
	if large {
		if totalSectors16 != 0 {
			return errors.New("FAT32 must set totalSectors16 to zero")
		} else if totalSectors32 == 0 {
			return errors.New("FAT32 must set totalSectors32 to something other than zero")
		}
	} else {
		if totalSectors16 == 0 && totalSectors32 == 0 {
			return errors.New("FAT12/16 must set either totalSectors16 or totalSectors32, not neither")
		} else if totalSectors16 != 0 && totalSectors32 != 0 {
			return errors.New("FAT12/16 must set at most one of totalSectors16 or totalSectors32, not both")
		}
	}

	sectorsPerFAT16 := b.SectorsPerFAT16()
	if large && sectorsPerFAT16 != 0 {
		return errors.New("FAT32 must set sectorsPerFAT16 to zero")
	} else if !large && sectorsPerFAT16 == 0 {
		return errors.New("FAT12/16 must set sectorsPerFAT16 to something other than zero")
	}
	return nil
}

// Shared bootsector fields between FAT12/16 and FAT32, but at different offsets.
type bootsectorSuffix struct {
	driveNumber uint8     // Drive Number: 0x80 or 0x00
	reserved1   uint8     // Zero
	extBootSig  uint8     // bootSigExtended
	volumeID    [4]uint8  // Volume Serial Number (usually related to creation time)
	volumeLabel [11]uint8 // Volume Label
	fsType      [8]uint8  // FS Type (either FAT12, FAT16 or FAT32)
}

func (b *bootsectorSuffix) validate() error {
	if b.driveNumber != driveNumberDisk && b.driveNumber != driveNumberFloppy {
		return fmt.Errorf("Expected drive number %x, found: %x", driveNumberDisk, b.driveNumber)
	}
	if b.extBootSig != bootSigExtended {
		return fmt.Errorf("Expected boot signature: %x, found %x", bootSigExtended, b.extBootSig)
	}

	return nil
}
