This Guide contains my setup notes for the HP Zbook Ultra G1A.
My specs: AMD AI MAX Pro 390, Radeon 8050S, 64GB RAM (these notes are applicable for other configs)
Parts of these notes may be OS specific to Fedora 44 KDE.
Press F10 during boot to enter bios. (F1 system info, F2 system diag, F3 option ROM, F8/F9 boot menu, F10 Bios setup, F11 system restore)
Settings
- Security tab
- Pluton Security Processor off
- >> Secure Platform Management
- HP Cloud managed off
- Remote Device management off
- Advanced tab
- >> Port Options
- USB Legacy Port Charging off (wastes significant battery when laptop is powered off)
- >> Power Management Options
- Battery Health Manager maximize (!caps battery to 80%, this is a personal preference to extend battery lifespan)
- >> Port Options
Update Bios
The most reliable method is to use a usb-c to ethernet adapter and connect to ethernet, then in the bios you can update thorugh the network ("check hp.com for bios updates").
Otherwise this guide could work, but it did not work for me; I also tried detecting the .bin on a Fat32-formatted usb.
Sometimes the graphics memory setting can be changed by a bios update, you may have to change this back to you original value (if using shared then set this to 512MB)
If your fans ramp to 100% or cold booting is taking a long time then perform a hard reset: 1. shut down and unplug everything, 2.hold power button for 30s and wait until caps lock light flashes (the system will boot, force shutdown, then the caps light will flash during this process).
Set 48GB of unified/shared GPU/CPU memory (for 64GB ram laptop), set immou, and improve power saving:
In advanced bios set gpu memory to 512MB (this is the reserved portion, shared memory is "added on" to this value).
sudo grubby --update-kernel=ALL --args='amd_pstate=active amd_iommu=on iommu=pt ttm.pages_limit=12582912 ttm.page_pool_size=12582912'- Check updated params with
sudo grubby --info=ALL - for size and limit use pages = (wanted_GB * 1024 * 1024 * 1024) / 4096 = wanted_GB * 262144
- immou info: https://instinct.docs.amd.com/projects/amdgpu-docs/en/latest/conceptual/iommu.html
- https://blog.linux-ng.de/2025/07/13/getting-information-about-amd-apus/
- check for GTT (unified) memory after reboot: sudo dmesg | grep GTT
cd ~
sudo dnf in python3.14-venv
python3 -m venv .venv
source .venv/bin/activate
pip install ipykernel ipython bash_kernel
ipython kernel install --user --name=venv
python -m ipykernel install --user --name=venv
python -m bash_kernel.install
echo "alias venv='source ~/.venv/bin/activate'" >> .bashrcUse venv in a terminal to activate the environment.
Do not change your bashrc to activate the env automatically, programs do not expect this (could lead to weird errors).
sudo dnf install rocm --setopt=install_weak_deps=False
# add user to groups
sudo usermod -a -G video,render $LOGNAME
# not a bad idea to restart at this point
pip3 install torch torchvision --index-url https://download.pytorch.org/whl/rocm7.2
# from: https://pytorch.org/get-started/locally/Next we can run a ROCm test script.
Python Code test_rocm.py
import torch, grp, pwd, os, subprocess
devices = []
try:
print("\n\nChecking ROCM support...")
result = subprocess.run(['rocminfo'], stdout=subprocess.PIPE)
cmd_str = result.stdout.decode('utf-8')
cmd_split = cmd_str.split('Agent ')
for part in cmd_split:
item_single = part[0:1]
item_double = part[0:2]
if item_single.isnumeric() or item_double.isnumeric():
new_split = cmd_str.split('Agent '+item_double)
device = new_split[1].split('Marketing Name:')[0].replace(' Name: ', '').replace('\n','').replace(' ','').split('Uuid:')[0].split('*******')[1]
devices.append(device)
if len(devices) > 0:
print('GOOD: ROCM devices found: ', len(devices))
else:
print('BAD: No ROCM devices found.')
print("Checking PyTorch...")
x = torch.rand(5, 3)
has_torch = False
len_x = len(x)
if len_x == 5:
has_torch = True
for i in x:
if len(i) == 3:
has_torch = True
else:
has_torch = False
if has_torch:
print('GOOD: PyTorch is working fine.')
else:
print('BAD: PyTorch is NOT working.')
print("Checking user groups...")
user = os.getlogin()
groups = [g.gr_name for g in grp.getgrall() if user in g.gr_mem]
gid = pwd.getpwnam(user).pw_gid
groups.append(grp.getgrgid(gid).gr_name)
if 'render' in groups and 'video' in groups:
print('GOOD: The user', user, 'is in RENDER and VIDEO groups.')
else:
print('BAD: The user', user, 'is NOT in RENDER and VIDEO groups. This is necessary in order to PyTorch use HIP resources')
if torch.cuda.is_available():
print("GOOD: PyTorch ROCM support found.")
t = torch.tensor([5, 5, 5], dtype=torch.int64, device='cuda')
print('Testing PyTorch ROCM support...')
if str(t) == "tensor([5, 5, 5], device='cuda:0')":
print('Everything fine! You can run PyTorch code inside of: ')
for device in devices:
print('---> ', device)
else:
print("BAD: PyTorch ROCM support NOT found.")
except:
print('Cannot find rocminfo command information. Unable to determine if AMDGPU drivers with ROCM support were installed.')venv
python test_rocm.pyResults
Checking ROCM support...
GOOD: ROCM devices found: 3
Checking PyTorch...
GOOD: PyTorch is working fine.
Checking user groups...
GOOD: The user tyler is in RENDER and VIDEO groups.
GOOD: PyTorch ROCM support found.
Testing PyTorch ROCM support...
Everything fine! You can run PyTorch code inside of:
---> AMD RYZEN AI MAX PRO 390 w/ Radeon 8050S
---> gfx1151
---> aie2pHowever sometimes that script does not catch everything. Training a simple NN with PyTorch is the best test.
mnist_train_nn.py
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,)) # https://stackoverflow.com/questions/63746182/correct-way-of-normalizing-and-scaling-the-mnist-dataset
])
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transform)
train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)
device = torch.device("cuda")
class FCNN(nn.Module):
def __init__(self):
super(FCNN, self).__init__()
self.flatten = nn.Flatten()
self.network = nn.Sequential(
nn.Linear(28*28, 256),
nn.ReLU(),
nn.Linear(256, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
def forward(self, x):
x = self.flatten(x)
return self.network(x)
model = FCNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=5e-4)
for epoch in range(8):
model.train()
running_loss = 0.0
for data, target in train_loader:
data, target = data.to(device), target.to(device)
outputs = model(data)
loss = criterion(outputs, target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
running_loss+=loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")
model.eval()
correct = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
outputs = model(data)
_, predicted = torch.max(outputs.data, 1)
correct += (predicted == target).sum().item()
print(f"Accuracy on test set: {100 * correct / len(test_dataset)}/100")Run the script:
venv
python mnist_train_nn.pyResults (randomization is not seeded, so there will be some variation)
Epoch 1, Loss: 0.2636644422555211
Epoch 2, Loss: 0.1020805029494406
Epoch 3, Loss: 0.06842198809221593
Epoch 4, Loss: 0.04938902005380484
Epoch 5, Loss: 0.03817743066423285
Epoch 6, Loss: 0.02998010665353915
Epoch 7, Loss: 0.023095546745948856
Epoch 8, Loss: 0.019655119564526577
Accuracy on test set: 97.97/100Find default CMake flags here.
These both build from source for gfx1151 (check architecture with rocminfo | grep -i gfx | head)
HIP Backend (faster, more finicky)
# requirements
sudo dnf in rocm-core-devel rocm-cmake rocm-devel
# activate virtual environment
venv
# install/compile llama-cpp-python
ROCM_HOME=/opt/rocm HIPCXX="$(hipconfig -l)/clang" HIP_PATH="$(hipconfig -R)" CMAKE_ARGS="-DGGML_HIP=on -DAMDGPU_TARGETS=gfx1151 -DGGML_HIP_ROCWMMA_FATTN=ON -DGGML_HIP_NO_VMM=ON -DCMAKE_BUILD_TYPE=Release" pip install llama-cpp-python --no-cache-dir --force-reinstall --no-binary :all:Set use_mmap=False in llama_cpp's Llama(...) (or --no-mmap when calling a llama.cpp binary), the HIP backend has issues with unified memory.
Test Llamma-cpp-python
Download a GGUF (e.g. here)
from llama_cpp import Llama
# Initialize the model
# Replace "path/to/model.gguf" with your actual local file path
llm = Llama(
model_path="/home/tyler/GGUFs/Qwen3.6-27B-UD-Q8_K_XL.gguf",
n_gpu_layers=-1, # -1 offloads all layers to GPU if supported
n_ctx=2048, # Context window size
use_mmap=False # NEEDED FOR HIP BACKEND
)
# Run a test prompt
response = llm.create_chat_completion(
messages=[
{"role": "user", "content": "Tell me a joke."}
]
)
print(response["choices"][0]["message"]["content"])Vulkan Backend (slower, more reliable)
# requirements
sudo dnf in vulkan-loader-devel vulkan-headers glslc glslang spirv-headers-devel
# activate virtual environment
venv
# install/compile llama-cpp-python
CMAKE_ARGS="-DGGML_VULKAN=on" pip install llama-cpp-python --no-cache-dir --force-reinstall --no-binary :all:Test Llamma-cpp-python
Download a GGUF (e.g. here)
from llama_cpp import Llama
# Initialize the model
# Replace "path/to/model.gguf" with your actual local file path
llm = Llama(
model_path="/home/tyler/GGUFs/Qwen3.6-27B-UD-Q8_K_XL.gguf",
n_gpu_layers=-1, # -1 offloads all layers to GPU if supported
n_ctx=2048, # Context window size
# use_mmap=False # not needed for vulkan backend
)
# Run a test prompt
response = llm.create_chat_completion(
messages=[
{"role": "user", "content": "Tell me a joke."}
]
)
print(response["choices"][0]["message"]["content"])To support the ISP camera use my installer: https://github.com/tylerebowers/amd-isp4-camera-sb
I have support for secure boot and use the v11 driver, it is a fork of the original installer.
Seeing "Wolf security" and "Powered by ... experiences" logos for every boot is so annoying. These can be replaced with a custom logo using these instructions: https://github.com/tylerebowers/HP-UEFI-Custom-Logo
See my Gist on remapping the copilot key using keyd.
An improved Mediatek wifi driver can be found as a DKMS module here.
Module status can be checked with sudo dkms status.