For ROMs and other memories in your DUT or outside it in your test environment, use behavioral models, ideally with a provided read() and write() API for quick access to content data. If no API, then write one, assuming the data is stored in publicly accessible array inside the model. You might have to dig / map addresses and data widths / byte lane muxing etc.
Once you have the above:
For sharing: have an interface to each ROM, containing a read()/write() function API that UVM can call (via a virtual interface) and which accesses the ROM model API to read (or write) data in zero time.
Or, use the uvm_reg (UVM Register Package) which has some support for memories, and backdoor access via DPI calls, which is an equivalent approach with some other added value (read about UVM Register Package here to find more)
For initialization: at time zero at the start of the run phase, or when you come out of reset, your testbench SV code can call the above API to preload ROM contents either from a file on disk (using usual verilog features for file access) or runtime generated static or random data, whichever suits your verification requirements best.
If you used uvm_reg, you can access the memory via sequences, but take note, it is better to write a single sequence to preload a whole memory array at once, rather than to call individual sequence operations for each word of a large memory.
It is almost always better to initialize a memory in zero time (aka back door access) than to initialize it a word at a time using the bus connection (with no verification benefit to you of those simulation cycles).