Get started with driver development

This guide provides step-by-step instructions that walk you through the basic workflows of building, running, debugging, and updating drivers in a Fuchsia system using the Fuchsia SDK.

Important: This guide is the driver equivalent of the Get started with the Fuchsia SDK guide. If you haven‘t already, it’s strongly recommended that you first complete the Get started with the Fuchsia SDK guide to become familiar with the comprehensive set of Fuchsia SDK-based workflows.

Complete the following sections:

  1. Prerequisites.
  2. Clone the SDK driver samples repository.
  3. Start the emulator.
  4. Build and load the sample driver.
  5. Build and run a tools component.
  6. Debug the sample driver.
  7. Modify and reload the sample driver.

Found an issue? Please let us know{:.external}.

1. Prerequisites {:#prerequisites}

This guide requires that your host machine meets the following criteria:

  • A Linux machine. (macOS is not supported yet.)
  • Has at least 15 GB of storage space.
  • Supports KVM{:.external} (Kernel Virtual Machine) for running a QEMU{:.external}-based emulator.
  • IPv6 is enabled.
  • Git{:.external} is installed.

2. Clone the SDK driver samples repository {:#clone-the-sdk-driver-samples-repository}

Clone the SDK driver samples repository{:.external} on your host machine. This repository contains sample driver components and the Bazel-based Fuchsia SDK.

The tasks include:

  • Bootstrap the SDK driver samples repository.
  • Verify that you can build the sample driver components and run ffx commands.

Do the following:

  1. In a terminal, change to your home directory:

    Note: This guide uses the home directory ($HOME) as a base directory. This is where a new work directory (drivers) will be created for this guide. You may also select a different base directory (for instance, cd $HOME/my-fuchsia-project).

    cd $HOME
    
  2. Clone the SDK driver samples repository:

    git clone https://fuchsia.googlesource.com/sdk-samples/drivers --recurse-submodules
    

    This creates a new directory named drivers, which clones the content of the SDK driver samples repository.

  3. Go to the new directory:

    cd drivers
    
  4. Run the bootstrap script to install Bazel and other required dependencies:

    scripts/bootstrap.sh
    
  5. To verify the Fuchsia SDK environment setup, build the sample drivers:

    tools/bazel build --config=fuchsia_x64 //src/qemu_edu/drivers:qemu_edu
    

    The first build may take a few minutes to download dependencies, such as Bazel build rules, Clang, and Fuchsia IDK (which includes the ffx tool).

    When finished successfully, it prints output similar to the following in the end:

    $ tools/bazel build --config=fuchsia_x64 //src/qemu_edu/drivers:qemu_edu
    ...
    INFO: Elapsed time: 156.844s, Critical Path: 34.80s
    INFO: 777 processes: 510 internal, 267 linux-sandbox.
    INFO: Build completed successfully, 777 total actions
    
  6. To verify that you can use the ffx tool in your environment, run the following command:

    tools/ffx sdk version
    

    This command prints output similar to the following:

    $ tools/ffx sdk version
    9.20220807.3.1
    

    At this point, you only need to confirm that you can run ffx commands without error. (However for your information, the output above shows the version 9.20220807.3.1, which indicates that this SDK was built and published on August 7, 2022.)

    Note: To ensure that you’re using the right version of ffx during development, consider updating your PATH to include the SDK‘s tools directory (for instance, export PATH="$PATH:$HOME/fuchsia-getting-started/tools"). However, if you don’t wish to update your PATH, ensure that you specify the relative path to this ffx tool (tools/ffx) whenever you run ffx commands.

3. Start the emulator {:#start-the-emulator}

Start the Fuchsia emulator on the host machine while configuring the emulator instance to use Fuchsia’s new driver framework (DFv2).

The tasks include:

  • Download Fuchsia's Workstation prebuilt image from Google Cloud Storage.
  • Start the Fuchsia emulator.
  • Set the emulator instance as your host machine’s default target device.
  • Start the Fuchsia package server.
  • Register the system package repository to the emulator instance.

Do the following:

  1. Download the latest Workstation image for the emulator:

    tools/ffx product-bundle get workstation_eng.qemu-x64 --repository workstation-packages
    

    This command may take a few minutes to download the image and product metadata.

    Note: If the product-bundle command fails with an error due to multiple product bundle instances or SDK versions, clean up the environment before proceeding.

    Once the download is finished, the ffx product-bundle get command creates a local Fuchsia package repository named workstation-packages on your host machine. This package repository hosts additional system packages for this Workstation prebuilt image. Later in Step 8 you’ll register this package repository to the emulator instance.

  2. Stop all emulator instances:

    tools/ffx emu stop --all
    
  3. Start the Fuchsia emulator:

    tools/ffx emu start workstation_eng.qemu-x64 --headless \
      --kernel-args "driver_manager.use_driver_framework_v2=true" \
      --kernel-args "driver_manager.root-driver=fuchsia-boot:///#meta/platform-bus.cm" \
      --kernel-args "devmgr.enable-ephemeral=true"
    

    This command starts a headless emulator instance running the Workstation prebuilt image.

    When the instance is up and running, the command prints output similar to the following:

    $ tools/ffx emu start workstation_eng.qemu-x64 --headless \
      --kernel-args "driver_manager.use_driver_framework_v2=true" \
      --kernel-args "driver_manager.root-driver=fuchsia-boot:///#meta/platform-bus.cm" \
      --kernel-args "devmgr.enable-ephemeral=true"
    Creating SSH key pair: /home/alice/.ssh/fuchsia_ed25519
    Writing authorized_keys file: /home/alice/.ssh/fuchsia_authorized_keys
    Logging to "/home/alice/.local/share/Fuchsia/ffx/emu/instances/fuchsia-emulator/emulator.log"
    Waiting for Fuchsia to start (up to 60 seconds).
    Emulator is ready.
    
  4. Verify that the new emulator instance is running:

    tools/ffx emu list
    

    This command prints output similar to the following:

    $ tools/ffx emu list
    [Active]  fuchsia-emulator
    
  5. Set the default target device:

    tools/ffx target default set fuchsia-emulator
    

    This command exits silently without output.

  6. Start the Fuchsia package server:

    tools/ffx repository server start
    

    This command prints output similar to the following:

    $ tools/ffx repository server start
    ffx repository server is listening on [::]:8083
    
  7. Check the list of Fuchsia package repositories available on your host machine:

    tools/ffx repository list
    

    This command prints output similar to the following:

    $ tools/ffx repository list
    +-----------------------+------+-------------------------------------------------------------------------------------------------+
    | NAME                  | TYPE | EXTRA                                                                                           |
    +=======================+======+=================================================================================================+
    | workstation-packages* | pm   | /home/alice/.local/share/Fuchsia/ffx/pbms/4751486831982119909/workstation_eng.qemu-x64/packages |
    +-----------------------+------+-------------------------------------------------------------------------------------------------+
    

    Notice a package repository (workstation-packages) is created for the Workstation prebuilt image.

  8. Register the workstation-packages package repository to the target device:

    tools/ffx target repository register -r workstation-packages --alias fuchsia.com --alias chromium.org
    

    This command exits silently without output.

4. Build and load the sample driver {:#build-and-load-the-sample-driver}

The Fuchsia emulator (launched in the Start the emulator section above) is configured to create a virtual device named edu, which is an educational device for writing drivers. In the previous section, when the emulator started, Fuchsia’s driver framework detected this edu device in the system, but it wasn’t able to find a driver that could serve the edu device. So the edu device was left unmatched.

In this section, we build and publish the qemu_edu sample driver (which is a Fuchsia component). Upon detecting a new driver, the driver framework will discover that this new qemu_edu driver is a match for the edu device. Once matched, the qemu_edu driver starts providing the edu device’s services (capabilities) to other components in the system – one of the services provided by the edu device is that it computes a factorial given an integer.

The tasks include:

  • View the drivers that are currently loaded in the emulator instance.
  • Build and publish the qemu_edu driver component.
  • Verify that the qemu_edu driver is loaded to the emulator instance.
  • View detailed information on the qemu_edu component.

Do the following:

  1. View the list of the currently loaded drivers:

    tools/ffx driver list --loaded
    

    This command prints output similar to the following:

    $ tools/ffx driver list --loaded
    fuchsia-boot:///#meta/block.core.cm
    fuchsia-boot:///#meta/bus-pci.cm
    fuchsia-boot:///#meta/fvm.cm
    fuchsia-boot:///#meta/hid.cm
    fuchsia-boot:///#meta/intel-rtc.cm
    fuchsia-boot:///#meta/netdevice-migration.cm
    fuchsia-boot:///#meta/network-device.cm
    fuchsia-boot:///#meta/pc-ps2.cm
    fuchsia-boot:///#meta/platform-bus-x86.cm
    fuchsia-boot:///#meta/platform-bus.cm
    fuchsia-boot:///#meta/ramdisk.cm
    fuchsia-boot:///#meta/sysmem.cm
    fuchsia-boot:///#meta/virtio_block.cm
    fuchsia-boot:///#meta/virtio_ethernet.cm
    fuchsia-pkg://fuchsia.com/virtual_audio#meta/virtual_audio_driver.cm
    
  2. Build and publish the qemu_edu driver component:

    tools/bazel run --config=fuchsia_x64 //src/qemu_edu/drivers:pkg.component
    

    This command prints output similar to the following:

    $ tools/bazel run --config=fuchsia_x64 //src/qemu_edu/drivers:pkg.component
    INFO: Analyzed target //src/qemu_edu/drivers:pkg.component (8 packages loaded, 498 targets configured).
    INFO: Found 1 target...
    Target //src/qemu_edu/drivers:pkg.component up-to-date:
      bazel-bin/src/qemu_edu/drivers/pkg.component_run_component.sh
    INFO: Elapsed time: 43.548s, Critical Path: 35.04s
    INFO: 795 processes: 519 internal, 275 linux-sandbox, 1 local.
    INFO: Build completed successfully, 795 total actions
    INFO: Build completed successfully, 795 total actions
    added repository bazel.pkg.component
    Registering fuchsia-pkg://bazel.pkg.component/qemu_edu#meta/qemu_edu.cm
    Successfully bound:
    Node 'root.sys.platform.platform-passthrough.PCI0.bus.00_06_0_', Driver 'fuchsia-pkg://bazel.pkg.component/qemu_edu#meta/qemu_edu.cm'.
    
  3. Verify that the qemu_edu driver is now loaded to the Fuchsia emulator instance:

    tools/ffx driver list --loaded
    

    This command prints output similar to the following:

    $ tools/ffx driver list --loaded
    fuchsia-boot:///#meta/bus-pci.cm
    fuchsia-boot:///#meta/fvm.cm
    fuchsia-boot:///#meta/hid.cm
    fuchsia-boot:///#meta/intel-rtc.cm
    fuchsia-boot:///#meta/netdevice-migration.cm
    fuchsia-boot:///#meta/network-device.cm
    fuchsia-boot:///#meta/pc-ps2.cm
    fuchsia-boot:///#meta/platform-bus-x86.cm
    fuchsia-boot:///#meta/platform-bus.cm
    fuchsia-boot:///#meta/ramdisk.cm
    fuchsia-boot:///#meta/sysmem.cm
    fuchsia-boot:///#meta/virtio_block.cm
    fuchsia-boot:///#meta/virtio_ethernet.cm
    fuchsia-pkg://fuchsia.com/virtual_audio#meta/virtual_audio_driver.cm
    {{ '<strong>' }}fuchsia-pkg://bazel.pkg.component/qemu_edu#meta/qemu_edu.cm{{ '</strong>' }}
    fuchsia-boot:///#meta/block.core.cm
    

    Notice that the qemu_edu driver is shown in the loaded drivers list.

  4. View the qemu_edu component information:

    tools/ffx component show qemu_edu.cm
    

    This command prints output similar to the following:

    $ tools/ffx component show qemu_edu.cm
                   Moniker:  /bootstrap/universe-pkg-drivers:root.sys.platform.platform-passthrough.PCI0.bus.00_06_0_
                       URL:  fuchsia-pkg://bazel.pkg.component/qemu_edu#meta/qemu_edu.cm
               Instance ID:  None
                      Type:  CML Component
           Component State:  Resolved
     Incoming Capabilities:  /svc/fuchsia.device.fs.Exporter
                             /svc/fuchsia.driver.compat.Service
                             /svc/fuchsia.logger.LogSink
      Exposed Capabilities:  fuchsia.hardware.qemuedu.Service
               Merkle root:  b4c34c971b6e191a021f59be92feec56868ce3c1602b88fb094a4f07923d4e1e
           Execution State:  Running
              Start reason:  Instance is in a single_run collection
     Outgoing Capabilities:  fuchsia.hardware.qemuedu.Service
    
  5. View the device logs of the qemu_edu driver:

    tools/ffx log --filter qemu_edu dump
    

    This command prints output similar to the following:

    $ tools/ffx log --filter qemu_edu dump
    ...
    [173.618][pkg-resolver][pkg-resolver][I] resolved fuchsia-pkg://bazel.pkg.component/qemu_edu as fuchsia-pkg://bazel.pkg.component/qemu_edu to 957cd123aba43515a5acc8b95a2abfecba3d714655f3a2a4e581c13ca0db6f7d with TUF
    [173.618][pkg-resolver][pkg-resolver][I] get_hash for fuchsia-pkg://bazel.pkg.component/qemu_edu as fuchsia-pkg://bazel.pkg.component/qemu_edu to 957cd123aba43515a5acc8b95a2abfecba3d714655f3a2a4e581c13ca0db6f7d with TUF
    [173.623][driver_index][driver_index,driver][I] Registered driver successfully: fuchsia-pkg://bazel.pkg.component/qemu_edu#meta/qemu_edu.cm.
    [173.653][pkg-resolver][pkg-resolver][I] Fetching blobs for fuchsia-pkg://bazel.pkg.component/qemu_edu: []
    [173.656][pkg-resolver][pkg-resolver][I] resolved fuchsia-pkg://bazel.pkg.component/qemu_edu as fuchsia-pkg://bazel.pkg.component/qemu_edu to 957cd123aba43515a5acc8b95a2abfecba3d714655f3a2a4e581c13ca0db6f7d with TUF
    [173.662][driver_manager][driver_manager.cm][I]: [driver_runner.cc:377] Binding fuchsia-pkg://bazel.pkg.component/qemu_edu#meta/qemu_edu.cm to  00_06_0_
    [173.891][universe-pkg-drivers:root.sys.platform.platform-passthrough.PCI0.bus.00_06_0_][qemu-edu,driver][I]: [src/qemu_edu/qemu_edu.cc:117] edu device version major=1 minor=0
    

5. Build and run a tools component {:#build-and-run-a-tools-component}

The qemu_edu driver sample has a “tools” component named eductl, which can interact with the sample driver. Developers create these tools components for testing and debugging drivers during development.

In this case, the eductl component contacts the qemu_edu driver and passes an integer as input. The driver (using the resource of the edu virtual device) computes the integer's factorial and returns the result to the eductl component. The component then prints the result in the log.

The tasks include:

  • Build and run the eductl component.
  • Verify that the component can interact with the qemu_edu driver.

Do the following:

  1. Build and run the eductl component:

    tools/bazel run --config=fuchsia_x64 //src/qemu_edu/tools:pkg.component
    

    This command prints output similar to the following:

    $ tools/bazel run --config=fuchsia_x64 //src/qemu_edu/tools:pkg.component
    INFO: Analyzed target //src/qemu_edu/tools:pkg.component (1 packages loaded, 19 targets configured).
    INFO: Found 1 target...
    Target //src/qemu_edu/tools:pkg.component up-to-date:
      bazel-bin/src/qemu_edu/tools/pkg.component_run_component.sh
    INFO: Elapsed time: 2.189s, Critical Path: 1.63s
    INFO: 23 processes: 7 internal, 15 linux-sandbox, 1 local.
    INFO: Build completed successfully, 23 total actions
    INFO: Build completed successfully, 23 total actions
    added repository bazel.pkg.component
    URL: fuchsia-pkg://bazel.pkg.component/eductl#meta/eductl.cm
    Moniker: /core/ffx-laboratory:eductl
    Creating component instance...
    Starting component instance...
    Success! The component instance has been started.
    
  2. View the device logs:

    tools/ffx log --filter qemu_edu --filter eductl dump
    

    The device logs contain lines similar to the following:

    $ tools/ffx log --filter qemu_edu --filter eductl dump
    ...
    [214.156][universe-pkg-drivers:root.sys.platform.platform-passthrough.PCI0.bus.00_06_0_][qemu-edu,driver][I]: [src/qemu_edu/qemu_edu.cc:234] Replying with factorial=479001600
    [214.157][ffx-laboratory:eductl][][I] Factorial(12) = 479001600
    

    These lines show that the driver replied the result of factorial=479001600 to the eductl component, which previously passed 12 as input to the driver. (For the default input, see this eductl.cml file.)

6. Debug the sample driver {:#debug-the-sample-driver}

Use the Fuchsia debugger (zxdb) to step through the sample driver’s code as the driver is running on the emulator instance.

The tasks include:

  • Identify the driver host (which is a component) that is running the qemu_edu driver.
  • Start the Fuchsia debugger and connect it to the emulator instance.
  • Attach the debugger to the driver host.
  • Set a breakpoint on the driver’s code.
  • Run the tools component, which triggers the driver to execute its instructions.
  • Step through the driver’s code.

Do the following:

  1. View the list of the running driver hosts:

    tools/ffx driver list-hosts
    

    This command prints output similar to the following:

    $ tools/ffx driver list-hosts
    Driver Host: 4690
        fuchsia-boot:///#meta/block.core.cm
        fuchsia-boot:///#meta/bus-pci.cm
        fuchsia-boot:///#meta/fvm.cm
        fuchsia-boot:///#meta/hid.cm
        fuchsia-boot:///#meta/netdevice-migration.cm
        fuchsia-boot:///#meta/network-device.cm
        fuchsia-boot:///#meta/platform-bus-x86.cm
        fuchsia-boot:///#meta/platform-bus.cm
        fuchsia-boot:///#meta/ramdisk.cm
        fuchsia-boot:///#meta/sysmem.cm
        fuchsia-boot:///#meta/virtio_block.cm
        fuchsia-boot:///#meta/virtio_ethernet.cm
        fuchsia-boot:///#meta/zxcrypt.cm
        fuchsia-pkg://fuchsia.com/virtual_audio#meta/virtual_audio_driver.cm
    
    Driver Host: 7820
        fuchsia-boot:///#meta/intel-rtc.cm
    
    Driver Host: 7903
        fuchsia-boot:///#meta/pc-ps2.cm
    
    Driver Host: 50125
        fuchsia-pkg://bazel.pkg.component/qemu_edu#meta/qemu_edu.cm
    

    Make a note of the PID of the qemu_edu driver host (50125 in the example above).

  2. Start the Fuchsia debugger:

    tools/ffx debug connect
    

    This command prints output similar to the following:

    $ tools/ffx debug connect
    Connecting (use "disconnect" to cancel)...
    Connected successfully.
    👉 To get started, try "status" or "help".
    [zxdb]
    
  3. Attach the debugger to the qemu_edu driver host:

    Replace PID with the PID of the qemu_edu driver host identified in Step 1, for example:

    [zxdb] attach 50125
    

    This command prints output similar to the following:

    [zxdb] attach 50125
    Attached Process 1 state=Running koid=50125 name=driver_host2.cm
    Downloading symbols...
    Symbol downloading complete. 7 succeeded, 0 failed.
    [zxdb]
    
  4. Set a breakpoint at the driver’s ComputeFactorial function:

    This command prints output similar to the following:

    [zxdb] break QemuEduDriver::ComputeFactorial
    Created Breakpoint 1 @ QemuEduDriver::ComputeFactorial
       203 void QemuEduDriver::ComputeFactorial(ComputeFactorialRequestView request,
     {{ '<strong>' }}◉ 204                                      ComputeFactorialCompleter::Sync& completer) { {{ '</strong>' }}
       205   // Write a value into the factorial register.
    [zxdb]
    
  5. In different terminal, run the tools component:

    Note: In this new terminal, make sure that you change to the same work directory (for instance, cd $HOME/drivers).

    tools/bazel run --config=fuchsia_x64 //src/qemu_edu/tools:pkg.component
    

    In the zxdb terminal, verify that the debugger is stopped at the driver’s ComputeFactorial function, for example:

    🛑 thread 2 on bp 1 qemu_edu::QemuEduDriver::ComputeFactorial(qemu_edu::QemuEduDriver*, fidl::WireServer<fuchsia_hardware_qemuedu::Device>::ComputeFactorialRequestView, fidl::Completer<fidl::internal::WireCompleterBase<fuchsia_hardware_qemuedu::Device::ComputeFactorial> >::Sync&)  qemu_edu.cc:218
       202 // Driver Service: Compute factorial on the edu device
       203 void QemuEduDriver::ComputeFactorial(ComputeFactorialRequestView request,
     {{ '<strong>' }}▶ 204                                      ComputeFactorialCompleter::Sync& completer) { {{ '</strong>' }}
       205   // Write a value into the factorial register.
       206   uint32_t input = request->input;
    [zxdb]
    
  6. In the zxdb terminal, view the source code around the current breakpoint:

    This command prints output similar to the following:

    [zxdb] list
       199 // [END interrupt_mmio]
       200
       201 // [START compute_factorial]
       202 // Driver Service: Compute factorial on the edu device
       203 void QemuEduDriver::ComputeFactorial(ComputeFactorialRequestView request,
     {{ '<strong>' }}▶ 204                                      ComputeFactorialCompleter::Sync& completer) { {{ '</strong>' }}
       205   // Write a value into the factorial register.
       206   uint32_t input = request->input;
       207
       208   mmio_->Write32(input, edu_device_registers::kFactorialCompoutationOffset);
       209
       210   // Busy wait on the factorial status bit.
       211   while (true) {
       212     const auto status = edu_device_registers::Status::Get().ReadFrom(&*mmio_);
       213     if (!status.busy())
       214       break;
    [zxdb]
    
  7. In the zxdb terminal, step through the code using the next command until the value of factorial is read from the device (that is, until the line 220 is reached):

    The last next command prints output similar to the following:

    ...
    [zxdb] next
    🛑 thread 2 qemu_edu::QemuEduDriver::ComputeFactorial(qemu_edu::QemuEduDriver*, fidl::WireServer<fuchsia_hardware_qemuedu::Device>::ComputeFactorialRequestView, fidl::Completer<fidl::internal::WireCompleterBase<fuchsia_hardware_qemuedu::Device::ComputeFactorial> >::Sync&)  qemu_edu.cc:234
       218   uint32_t factorial = mmio_->Read32(edu_device_registers::kFactorialCompoutationOffset);
       219
     {{ '<strong>' }}▶ 220   FDF_SLOG(INFO, "Replying with", KV("factorial", factorial));{{ '</strong>' }}
       221   completer.Reply(factorial);
       222 }
    [zxdb]
    
  8. Print the factorial variable:

    This command prints output similar to the following:

    [zxdb] print factorial
    479001600
    [zxdb]
    
  9. To exit the zxdb terminal, type exit or press Ctrl-D.

    Note: For more information on usages and best practices on zxdb, see the zxdb user guide.

7. Modify and reload the sample driver {:#modify-and-reload-the-sample-driver}

Update the source code of the sample driver and reload it to the emulator instance.

The tasks include:

  • Restart the emulator instance to unload the qemu_edu driver.
  • Update the source code of the qemu_edu driver.
  • Load the updated driver.
  • Run the tools component to verify the change.

Do the following:

  1. Stop the emulator instance:

    tools/ffx emu stop
    

    This command stops the currently running emulator instance.

  2. Start a new instance of the Fuchsia emulator:

    tools/ffx emu start workstation_eng.qemu-x64 --headless \
      --kernel-args "driver_manager.use_driver_framework_v2=true" \
      --kernel-args "driver_manager.root-driver=fuchsia-boot:///#meta/platform-bus.cm" \
      --kernel-args "devmgr.enable-ephemeral=true"
    

    This command starts a headless emulator instance running the Workstation prebuilt image.

  3. Use a text editor to open the source code of the sample driver, for example:

    nano src/qemu_edu/drivers/qemu_edu.cc
    
  4. In the QemuEduDriver::ComputeFactorial function, between the line uint32_t factorial = mmio_->Read32(regs::kFactorialCompoutationOffset); (Line 218) and the FDF_SLOG() call (Line 220), add the following line:

    factorial=12345;
    

    The function should look like below:

    void QemuEduDriver::ComputeFactorial(ComputeFactorialRequestView request,
                                         ComputeFactorialCompleter::Sync& completer) {
      // Write a value into the factorial register.
      uint32_t input = request->input;
    
      mmio_->Write32(input, regs::kFactorialCompoutationOffset);
    
      // Busy wait on the factorial status bit.
      while (true) {
        const auto status = regs::Status::Get().ReadFrom(&*mmio_);
        if (!status.busy())
          break;
      }
    
      // Return the result.
      uint32_t factorial = mmio_->Read32(regs::kFactorialCompoutationOffset);
      {{ '<strong>' }}factorial = 12345;{{ '</strong>' }}
      FDF_SLOG(INFO, "Replying with", KV("factorial", factorial));
      completer.Reply(factorial);
    }
    

    The function is now updated to return the value of 12345 only.

  5. Save the file and close the text editor.

  6. Rebuild and run the modified sample driver:

    tools/bazel run --config=fuchsia_x64 //src/qemu_edu/drivers:pkg.component
    
  7. Run the tools component:

    tools/bazel run --config=fuchsia_x64 //src/qemu_edu/tools:pkg.component
    
  8. To verify that change, view the device logs:

    tools/ffx log --filter qemu_edu --filter eductl dump
    

    The device logs contain lines similar to the following:

    $ tools/ffx log --filter qemu_edu --filter eductl dump
    ...
    [94.914][universe-pkg-drivers:root.sys.platform.platform-passthrough.PCI0.bus.00_06_0_][qemu-edu,driver][I]: [src/qemu_edu/qemu_edu.cc:234] Replying with factorial=12345
    [94.916][ffx-laboratory:eductl][][I] Factorial(12) = 12345
    

    These lines show that the qemu_edu driver replied with the hardcoded value of factorial=12345 to the eductl tools component.

Congratulations! You’re now all set with the Fuchsia driver development!

Next steps {:#next-steps}

Learn more about how the qemu_edu driver works in Codelab: QEMU edu driver.

Appendices

Clean up the environment {:#clean-up-the-environment}

If you run into a problem while following this guide and decide to start over from the beginning, consider running the commands below to clean up your development environment (that is, to clean up directories, build artifacts, downloaded files, symlinks, configuration settings, and more).

Remove the package repositories created in this guide:

tools/ffx repository remove workstation-packages
tools/ffx repository server stop

Remove all existing configurations and data of ffx:

tools/ffx daemon stop
rm -rf $HOME/.local/share/Fuchsia/ffx

When Bazel fails to build, try the commands below:

Caution: Running bazel clean or deleting the $HOME/.cache/bazel directory deletes all the artifacts downloaded by Bazel, which can be around 4 GB. This means Bazel will need to download those dependencies again the next time you run bazel build.

tools/bazel clean --expunge
tools/bazel shutdown && rm -rf $HOME/.cache/bazel

Remove the drivers directory and its artifacts:

Caution: If the SDK samples repository is cloned to a different location than $HOME/drivers, adjust the directory path in the command below. Be extremely careful with the directory path when you run the `rm -rf

rm -rf $HOME/drivers

Other clean up commands:

killall ffx
killall pm