Skip to content

Instantly share code, notes, and snippets.

@LeebDeveloper
Created March 6, 2024 09:45
Show Gist options
  • Save LeebDeveloper/357ed7afcebba1b009c59c559d4c748b to your computer and use it in GitHub Desktop.
Save LeebDeveloper/357ed7afcebba1b009c59c559d4c748b to your computer and use it in GitHub Desktop.
Using ioctl to obtain serial number from ATA drive
package main
import (
"fmt"
"os"
"unsafe"
"syscall"
)
const (
HDIO_DRIVE_CMD = 0x031f // execute a special drive command
)
const (
WIN_IDENTIFY = 0xEC // ask drive to identify itself
)
const START_SERIAL = 10
const LENGTH_SERIAL = 10
func little_endian_to_big_endian(input []byte) []byte {
output := make([]byte, len(input))
for i := 0; i < len(input); i+=2 {
output[i] = input[i + 1]
output[i + 1] = input[i]
}
return output
}
func GetDiskSerial(device *os.File) string {
buffer := make([]byte, 4 + 512) // Command definition + buffer for data
buffer[0] = WIN_IDENTIFY
buffer[3] = 1 // Buffer size in some internal struct sizes
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(device.Fd()),
uintptr(HDIO_DRIVE_CMD),
uintptr(unsafe.Pointer(&buffer[0])))
if err != 0 {
fmt.Println(err)
return ""
}
serial := string(little_endian_to_big_endian(buffer[4 + START_SERIAL * 2: 2 + (START_SERIAL + LENGTH_SERIAL)*2]))
return serial
}
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: driveserial /path/to/disk/device")
return
}
device, err := os.Open(os.Args[1])
if err != nil {
fmt.Println(err)
return
}
fmt.Println(GetDiskSerial(device))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment