Skip to content

Instantly share code, notes, and snippets.

@robertsinfosec
Last active November 21, 2024 02:37
Show Gist options
  • Save robertsinfosec/07a8bcb1d9e39680f0cb1886631053e9 to your computer and use it in GitHub Desktop.
Save robertsinfosec/07a8bcb1d9e39680f0cb1886631053e9 to your computer and use it in GitHub Desktop.
For a Linux machine, attempts to see how much RAM is installed and what kind, and determine what the maximum number of sticks and amount of RAM the current machine can support. If you want to run this on-the-fly and trust this source, from your Linux machine you can run: `curl -L https://tinyurl.com/ram-upgrade-check/raw | bash`
#!/bin/bash
# Script to determine maximum supported RAM, current RAM configuration,
# and specifications for upgrading RAM to maximum capacity.
set -euo pipefail
# Define color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Get FQDN of the current machine
FQDN=$(hostname -f)
# Get BIOS information
BIOS_MANUFACTURER=$(sudo dmidecode -s bios-vendor)
BIOS_VERSION=$(sudo dmidecode -s bios-version)
BIOS_RELEASE_DATE=$(sudo dmidecode -s bios-release-date)
SYSTEM_MANUFACTURER=$(sudo dmidecode -s system-manufacturer)
SYSTEM_PRODUCT_NAME=$(sudo dmidecode -s system-product-name)
SYSTEM_VERSION=$(sudo dmidecode -s system-version)
SYSTEM_SERIAL_NUMBER=$(sudo dmidecode -s system-serial-number)
SYSTEM_SKU=$(sudo dmidecode -s system-sku-number)
# Output system identification information
echo -e "${CYAN}FQDN.....................:${NC} $FQDN"
echo -e "${CYAN}BIOS Manufacturer........:${NC} $BIOS_MANUFACTURER"
echo -e "${CYAN}BIOS Version.............:${NC} $BIOS_VERSION"
echo -e "${CYAN}BIOS Release Date........:${NC} $BIOS_RELEASE_DATE"
echo -e "${CYAN}System Manufacturer......:${NC} $SYSTEM_MANUFACTURER"
echo -e "${CYAN}System Product Name......:${NC} $SYSTEM_PRODUCT_NAME"
echo -e "${CYAN}System Version...........:${NC} $SYSTEM_VERSION"
echo -e "${CYAN}System Serial Number.....:${NC} $SYSTEM_SERIAL_NUMBER"
echo -e "${CYAN}System SKU...............:${NC} $SYSTEM_SKU"
echo ""
echo -e "${GREEN}Starting RAM analysis...${NC}"
echo ""
# Function to check if a command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Ensure required commands are available
for cmd in dmidecode lscpu; do
if ! command_exists "$cmd"; then
echo -e "${RED}Error: Required command '$cmd' is not installed.${NC}" >&2
exit 1
fi
done
# Get detailed CPU information
CPU_MODEL=$(lscpu | grep -m1 "Model name" | awk -F: '{print $2}' | sed 's/^[ \t]*//')
CPU_VENDOR=$(lscpu | grep -m1 "Vendor ID" | awk -F: '{print $2}' | sed 's/^[ \t]*//')
CPU_FAMILY=$(lscpu | grep -m1 "CPU family" | awk -F: '{print $2}' | sed 's/^[ \t]*//')
CPU_MODEL_NUM=$(lscpu | grep -m1 "Model:" | awk -F: '{print $2}' | sed 's/^[ \t]*//')
# Get chipset information
CHIPSET=$(sudo dmidecode -t 2 2>/dev/null | grep -m1 "Product Name:" | awk -F: '{print $2}' | sed 's/^[ \t]*//' || echo "Unknown")
# Calculate total installed RAM
TOTAL_INSTALLED=$(free -b | grep "Mem:" | awk '{printf "%.0f\n", $2 / (1024*1024*1024)}')
echo -e "${CYAN}CPU Model................:${NC} $CPU_MODEL"
echo -e "${CYAN}Chipset..................:${NC} $CHIPSET"
echo -e "${CYAN}Total Installed RAM......:${NC} ${TOTAL_INSTALLED} GB"
# Get BIOS-reported maximum memory capacity
MAX_MEMORY=$(sudo dmidecode -t 16 | grep "Maximum Capacity" | head -n1 | awk -F: '{print $2}' | sed 's/^[ \t]*//')
echo -e "${CYAN}BIOS Maximum RAM.........:${NC} $MAX_MEMORY"
# Convert BIOS max to GB for comparison
MAX_MEMORY_GB=$(echo "$MAX_MEMORY" | grep -o '[0-9]\+')
# Check if installed RAM exceeds BIOS-reported maximum
if [ "$TOTAL_INSTALLED" -gt "$MAX_MEMORY_GB" ]; then
echo -e "${YELLOW}Warning: Installed RAM (${TOTAL_INSTALLED} GB) exceeds BIOS-reported maximum (${MAX_MEMORY_GB} GB)${NC}"
echo -e "${YELLOW}This suggests the actual hardware supports more RAM than reported by BIOS${NC}"
fi
# Get CPU maximum memory support based on vendor
if [[ "$CPU_VENDOR" == *"Intel"* ]]; then
echo -e "${CYAN}CPU Memory Support.......:${NC} Check https://ark.intel.com/content/www/us/en/ark/products/ for exact specifications"
echo -e "${YELLOW}Intel ${CPU_FAMILY} generation CPUs typically support up to 128GB RAM${NC}"
elif [[ "$CPU_VENDOR" == *"AMD"* ]]; then
echo -e "${CYAN}CPU Memory Support.......:${NC} Check https://www.amd.com/en/products/ for exact specifications"
echo -e "${YELLOW}Modern AMD CPUs typically support 128GB+ RAM${NC}"
fi
# Initialize arrays for memory information
declare -a SLOT_LOCATIONS
declare -a SLOT_SIZES
declare -a SLOT_TYPES
declare -a SLOT_SPEEDS
declare -a SLOT_MANUFACTURERS
declare -a SLOT_PART_NUMBERS
declare -a SLOT_FORM_FACTORS
echo -e "\n${GREEN}Collecting memory slot information...${NC}"
# Read dmidecode output and process each Memory Device section
TOTAL_SLOTS=0
while IFS= read -r line; do
if [[ $line =~ "Memory Device" ]]; then
# Read the block until an empty line
block=""
while IFS= read -r detail && [[ -n $detail ]]; do
block+="$detail"$'\n'
done
# Increment total slots
TOTAL_SLOTS=$((TOTAL_SLOTS + 1))
# Skip empty slots
if [[ $block =~ "Size: No Module Installed" ]]; then
SLOT_LOCATIONS+=("Slot $TOTAL_SLOTS")
SLOT_SIZES+=("(Empty)")
SLOT_TYPES+=("(Empty)")
SLOT_SPEEDS+=("(Empty)")
SLOT_MANUFACTURERS+=("(Empty)")
SLOT_PART_NUMBERS+=("(Empty)")
SLOT_FORM_FACTORS+=("(Empty)")
continue
fi
# Extract information
SIZE=$(echo "$block" | grep "^[[:space:]]*Size:" | head -n1 | awk -F: '{print $2}' | tr -d '[:space:]')
LOCATION=$(echo "$block" | grep "^[[:space:]]*Locator:" | head -n1 | awk -F: '{print $2}' | tr -d '[:space:]')
TYPE=$(echo "$block" | grep "^[[:space:]]*Type:" | grep -v "Type Detail" | head -n1 | awk -F: '{print $2}' | tr -d '[:space:]')
SPEED=$(echo "$block" | grep "^[[:space:]]*Speed:" | head -n1 | awk -F: '{print $2}' | tr -d '[:space:]')
MANUFACTURER=$(echo "$block" | grep "^[[:space:]]*Manufacturer:" | head -n1 | awk -F: '{print $2}' | tr -d '[:space:]')
PART_NUMBER=$(echo "$block" | grep "^[[:space:]]*Part Number:" | head -n1 | awk -F: '{print $2}' | tr -d '[:space:]')
FORM_FACTOR=$(echo "$block" | grep "^[[:space:]]*Form Factor:" | head -n1 | awk -F: '{print $2}' | tr -d '[:space:]')
# Add to arrays
SLOT_LOCATIONS+=("$LOCATION")
SLOT_SIZES+=("$SIZE")
SLOT_TYPES+=("$TYPE")
SLOT_SPEEDS+=("$SPEED")
SLOT_MANUFACTURERS+=("$MANUFACTURER")
SLOT_PART_NUMBERS+=("$PART_NUMBER")
SLOT_FORM_FACTORS+=("$FORM_FACTOR")
fi
done < <(sudo dmidecode -t 17)
# Function to infer the number of pins based on form factor and type
infer_pins() {
local form_factor=$1
local type=$2
case "$form_factor" in
"DIMM")
case "$type" in
"DDR3") echo "240" ;;
"DDR4") echo "288" ;;
"DDR5") echo "288" ;;
*) echo "Unknown" ;;
esac
;;
"SODIMM")
case "$type" in
"DDR3") echo "204" ;;
"DDR4") echo "260" ;;
"DDR5") echo "262" ;;
*) echo "Unknown" ;;
esac
;;
*)
echo "Unknown"
;;
esac
}
# Output current memory configuration
echo -e "\n${YELLOW}${BOLD}Current Memory Configuration:${NC}"
echo "----------------------------------------"
printf "${BOLD}%-10s %-10s %-10s %-15s %-15s %-20s %-10s${NC}\n" "Slot" "Size" "Type" "Speed" "Manufacturer" "Part Number" "Pins"
echo "---------------------------------------------------------------------------------------------"
for i in "${!SLOT_LOCATIONS[@]}"; do
PINS=$(infer_pins "${SLOT_FORM_FACTORS[$i]}" "${SLOT_TYPES[$i]}")
printf "%-10s %-10s %-10s %-15s %-15s %-20s %-10s\n" \
"${SLOT_LOCATIONS[$i]}" \
"${SLOT_SIZES[$i]}" \
"${SLOT_TYPES[$i]}" \
"${SLOT_SPEEDS[$i]}" \
"${SLOT_MANUFACTURERS[$i]}" \
"${SLOT_PART_NUMBERS[$i]}" \
"$PINS"
done
# Get specifications from first populated slot
FIRST_SLOT_INFO=$(sudo dmidecode -t 17 | awk '/Memory Device$/,/^$/' | head -n 30)
FORM_FACTOR=$(echo "$FIRST_SLOT_INFO" | grep "^[[:space:]]*Form Factor:" | head -n1 | awk -F: '{print $2}' | sed 's/^[ \t]*//')
VOLTAGE=$(echo "$FIRST_SLOT_INFO" | grep "^[[:space:]]*Configured Voltage:" | head -n1 | awk -F: '{print $2}' | sed 's/^[ \t]*//')
if [ -z "$VOLTAGE" ] || [ "$VOLTAGE" == "Unknown" ]; then
VOLTAGE="1.2 V (typical for DDR4)"
fi
ECC_TYPE=$(sudo dmidecode -t 16 | grep "Error Correction Type:" | head -n1 | awk -F: '{print $2}' | sed 's/^[ \t]*//')
if [ -z "$ECC_TYPE" ] || [ "$ECC_TYPE" == "None" ]; then
ECC="Non-ECC"
else
ECC="ECC"
fi
MEMORY_TYPE=$(echo "$FIRST_SLOT_INFO" | grep "^[[:space:]]*Type:" | grep -v "Type Detail" | head -n1 | awk -F: '{print $2}' | sed 's/^[ \t]*//')
MEMORY_SPEED=$(echo "$FIRST_SLOT_INFO" | grep "^[[:space:]]*Speed:" | head -n1 | awk -F: '{print $2}' | sed 's/^[ \t]*//')
echo -e "\n${YELLOW}${BOLD}Recommended RAM Specifications to Maximize Memory:${NC}"
echo "---------------------------------------------------"
echo -e "${CYAN}Form Factor..............:${NC} $FORM_FACTOR"
echo -e "${CYAN}Pins.....................:${NC} $(infer_pins "$FORM_FACTOR" "$MEMORY_TYPE")"
echo -e "${CYAN}Memory Type..............:${NC} $MEMORY_TYPE"
echo -e "${CYAN}Memory Speed.............:${NC} $MEMORY_SPEED"
echo -e "${CYAN}Voltage..................:${NC} $VOLTAGE"
echo -e "${CYAN}Error Correction.........:${NC} $ECC"
echo -e "${CYAN}Total Slots..............:${NC} $TOTAL_SLOTS"
# Calculate maximum capacity per slot
MAX_CAPACITY_NUM=$(echo "$MAX_MEMORY" | grep -o '[0-9]\+')
MAX_CAPACITY_UNIT=$(echo "$MAX_MEMORY" | grep -o '[A-Za-z]\+')
if [ "$MAX_CAPACITY_UNIT" == "GB" ]; then
MAX_CAPACITY_MB=$((MAX_CAPACITY_NUM * 1024))
elif [ "$MAX_CAPACITY_UNIT" == "MB" ]; then
MAX_CAPACITY_MB=$MAX_CAPACITY_NUM
else
MAX_CAPACITY_MB=0
fi
MAX_PER_SLOT=$((MAX_CAPACITY_MB / TOTAL_SLOTS))
echo -e "${CYAN}Maximum Capacity per Slot:${NC} $MAX_PER_SLOT MB"
# Output recommendation
echo ""
echo -e "${GREEN}To maximize your system's memory, you should install $TOTAL_SLOTS RAM module(s) with the following specifications:${NC}"
echo -e "- ${CYAN}Capacity per module....:${NC} ${MAX_PER_SLOT} MB"
echo -e "- ${CYAN}Type...................:${NC} $MEMORY_TYPE"
echo -e "- ${CYAN}Form Factor............:${NC} $FORM_FACTOR"
echo -e "- ${CYAN}Pins...................:${NC} $(infer_pins "$FORM_FACTOR" "$MEMORY_TYPE")"
echo -e "- ${CYAN}Memory Speed...........:${NC} $MEMORY_SPEED"
echo -e "- ${CYAN}Voltage................:${NC} $VOLTAGE"
echo -e "- ${CYAN}Error Correction.......:${NC} $ECC"
echo ""
echo -e "${YELLOW}* Note:${NC} The actual maximum memory capacity might be higher than reported by the BIOS. Consult your CPU and motherboard documentation for exact limits."
echo ""
echo -e "${GREEN}RAM analysis completed.${NC}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment